Update freetype to 8bb09b0fe4d9747bcf452a777cabed7d7ef435e2

Integrated patches from freetype2 git repository, up to hashval
8bb09b0fe4d9747bcf452a777cabed7d7ef435e2, which is post-2.5.2.

Most recent commit message from freetype git:
  [truetype] Simplify logic of rendering modes.

Noteworthy patches included:
  [sfnt] Fix handling of embedded bitmap strikes.
  [truetype] Improve handling of buggy embedded bitmap strikes.
  Add FT_FACE_FLAG_COLOR and FT_HAS_COLOR.

Change-Id: I4a22d96c9443c7a587475ca0a9c684843e144b18
diff --git a/Android.mk b/Android.mk
index e357397..2010736 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,6 +26,7 @@
 	src/base/ftsystem.c \
 	src/base/ftinit.c \
 	src/base/ftgasp.c \
+	src/gzip/ftgzip.c \
 	src/raster/raster.c \
 	src/sfnt/sfnt.c \
 	src/smooth/smooth.c \
diff --git a/include/freetype/config/ftconfig.h b/include/config/ftconfig.h
similarity index 88%
rename from include/freetype/config/ftconfig.h
rename to include/config/ftconfig.h
index 5dce30e..0770e78 100644
--- a/include/freetype/config/ftconfig.h
+++ b/include/config/ftconfig.h
@@ -27,11 +27,11 @@
   /* Note however that if some specific modifications are needed, we       */
   /* advise you to place a modified copy in your build directory.          */
   /*                                                                       */
-  /* The build directory is usually `freetype/builds/<system>', and        */
-  /* contains system-specific files that are always included first when    */
-  /* building the library.                                                 */
+  /* The build directory is usually `builds/<system>', and contains        */
+  /* system-specific files that are always included first when building    */
+  /* the library.                                                          */
   /*                                                                       */
-  /* This ANSI version should stay in `include/freetype/config'.           */
+  /* This ANSI version should stay in `include/config/'.                   */
   /*                                                                       */
   /*************************************************************************/
 
@@ -53,7 +53,7 @@
   /* These macros can be toggled to suit a specific system.  The current   */
   /* ones are defaults used to compile FreeType in an ANSI C environment   */
   /* (16bit compilers are also supported).  Copy this file to your own     */
-  /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+  /* `builds/<system>' directory, and edit it to port the engine.          */
   /*                                                                       */
   /*************************************************************************/
 
@@ -338,6 +338,7 @@
   /* These must be defined `static __inline__' with GCC.             */
 
 #if defined( __CC_ARM ) || defined( __ARMCC__ )  /* RVCT */
+
 #define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
 
   /* documentation is in freetype.h */
@@ -367,8 +368,10 @@
 
 #ifdef __GNUC__
 
-#if defined( __arm__ ) && !defined( __thumb__ )    && \
+#if defined( __arm__ )                                 && \
+    ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
     !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+
 #define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
 
   /* documentation is in freetype.h */
@@ -383,7 +386,11 @@
     __asm__ __volatile__ (
       "smull  %1, %2, %4, %3\n\t"       /* (lo=%1,hi=%2) = a*b */
       "mov    %0, %2, asr #31\n\t"      /* %0  = (hi >> 31) */
+#ifdef __clang__
+      "add.w  %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
+#else
       "add    %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
+#endif
       "adds   %1, %1, %0\n\t"           /* %1 += %0 */
       "adc    %2, %2, #0\n\t"           /* %2 += carry */
       "mov    %0, %1, lsr #16\n\t"      /* %0  = %1 >> 16 */
@@ -394,9 +401,13 @@
     return a;
   }
 
-#endif /* __arm__ && !__thumb__ && !( __CC_ARM || __ARMCC__ ) */
+#endif /* __arm__                      && */
+       /* ( __thumb2__ || !__thumb__ ) && */
+       /* !( __CC_ARM || __ARMCC__ )      */
+
 
 #if defined( __i386__ )
+
 #define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
 
   /* documentation is in freetype.h */
@@ -465,6 +476,66 @@
 
 #endif /* _MSC_VER */
 
+
+#if defined( __GNUC__ ) && defined( __x86_64__ )
+
+#define FT_MULFIX_ASSEMBLER  FT_MulFix_x86_64
+
+  static __inline__ FT_Int32
+  FT_MulFix_x86_64( FT_Int32  a,
+                    FT_Int32  b )
+  {
+    /* Temporarily disable the warning that C90 doesn't support */
+    /* `long long'.                                             */
+#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlong-long"
+#endif
+
+#if 1
+    /* Technically not an assembly fragment, but GCC does a really good */
+    /* job at inlining it and generating good machine code for it.      */
+    long long  ret, tmp;
+
+
+    ret  = (long long)a * b;
+    tmp  = ret >> 63;
+    ret += 0x8000 + tmp;
+
+    return (FT_Int32)( ret >> 16 );
+#else
+
+    /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine  */
+    /* code from the lines below.  The main issue is that `wide_a' is not  */
+    /* properly initialized by sign-extending `a'.  Instead, the generated */
+    /* machine code assumes that the register that contains `a' on input   */
+    /* can be used directly as a 64-bit value, which is wrong most of the  */
+    /* time.                                                               */
+    long long  wide_a = (long long)a;
+    long long  wide_b = (long long)b;
+    long long  result;
+
+
+    __asm__ __volatile__ (
+      "imul %2, %1\n"
+      "mov %1, %0\n"
+      "sar $63, %0\n"
+      "lea 0x8000(%1, %0), %0\n"
+      "sar $16, %0\n"
+      : "=&r"(result), "=&r"(wide_a)
+      : "r"(wide_b)
+      : "cc" );
+
+    return (FT_Int32)result;
+#endif
+
+#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) )
+#pragma GCC diagnostic pop
+#endif
+  }
+
+#endif /* __GNUC__ && __x86_64__ */
+
 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
 
 
@@ -492,6 +563,9 @@
 
 #endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
 
+#define FT_LOCAL_ARRAY( x )      extern const  x
+#define FT_LOCAL_ARRAY_DEF( x )  const  x
+
 
 #ifndef FT_BASE
 
diff --git a/include/freetype/config/ftheader.h b/include/config/ftheader.h
similarity index 88%
rename from include/freetype/config/ftheader.h
rename to include/config/ftheader.h
index 8371a31..b623629 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/config/ftheader.h
@@ -107,7 +107,7 @@
    *
    */
 #ifndef FT_CONFIG_CONFIG_H
-#define FT_CONFIG_CONFIG_H  <freetype/config/ftconfig.h>
+#define FT_CONFIG_CONFIG_H  <config/ftconfig.h>
 #endif
 
 
@@ -122,7 +122,7 @@
    *
    */
 #ifndef FT_CONFIG_STANDARD_LIBRARY_H
-#define FT_CONFIG_STANDARD_LIBRARY_H  <freetype/config/ftstdlib.h>
+#define FT_CONFIG_STANDARD_LIBRARY_H  <config/ftstdlib.h>
 #endif
 
 
@@ -137,7 +137,7 @@
    *
    */
 #ifndef FT_CONFIG_OPTIONS_H
-#define FT_CONFIG_OPTIONS_H  <freetype/config/ftoption.h>
+#define FT_CONFIG_OPTIONS_H  <config/ftoption.h>
 #endif
 
 
@@ -153,7 +153,7 @@
    *
    */
 #ifndef FT_CONFIG_MODULES_H
-#define FT_CONFIG_MODULES_H  <freetype/config/ftmodule.h>
+#define FT_CONFIG_MODULES_H  <config/ftmodule.h>
 #endif
 
   /* */
@@ -170,7 +170,7 @@
    *   base FreeType~2 API.
    *
    */
-#define FT_FREETYPE_H  <freetype/freetype.h>
+#define FT_FREETYPE_H  <freetype.h>
 
 
   /*************************************************************************
@@ -185,7 +185,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_ERRORS_H  <freetype/fterrors.h>
+#define FT_ERRORS_H  <fterrors.h>
 
 
   /*************************************************************************
@@ -198,7 +198,7 @@
    *   list of FreeType~2 module error offsets (and messages).
    *
    */
-#define FT_MODULE_ERRORS_H  <freetype/ftmoderr.h>
+#define FT_MODULE_ERRORS_H  <ftmoderr.h>
 
 
   /*************************************************************************
@@ -214,7 +214,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_SYSTEM_H  <freetype/ftsystem.h>
+#define FT_SYSTEM_H  <ftsystem.h>
 
 
   /*************************************************************************
@@ -230,7 +230,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_IMAGE_H  <freetype/ftimage.h>
+#define FT_IMAGE_H  <ftimage.h>
 
 
   /*************************************************************************
@@ -245,7 +245,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_TYPES_H  <freetype/fttypes.h>
+#define FT_TYPES_H  <fttypes.h>
 
 
   /*************************************************************************
@@ -260,7 +260,7 @@
    *   (Most applications will never need to include this file.)
    *
    */
-#define FT_LIST_H  <freetype/ftlist.h>
+#define FT_LIST_H  <ftlist.h>
 
 
   /*************************************************************************
@@ -273,7 +273,7 @@
    *   scalable outline management API of FreeType~2.
    *
    */
-#define FT_OUTLINE_H  <freetype/ftoutln.h>
+#define FT_OUTLINE_H  <ftoutln.h>
 
 
   /*************************************************************************
@@ -286,7 +286,7 @@
    *   API which manages multiple @FT_Size objects per face.
    *
    */
-#define FT_SIZES_H  <freetype/ftsizes.h>
+#define FT_SIZES_H  <ftsizes.h>
 
 
   /*************************************************************************
@@ -299,7 +299,7 @@
    *   module management API of FreeType~2.
    *
    */
-#define FT_MODULE_H  <freetype/ftmodapi.h>
+#define FT_MODULE_H  <ftmodapi.h>
 
 
   /*************************************************************************
@@ -312,7 +312,7 @@
    *   renderer module management API of FreeType~2.
    *
    */
-#define FT_RENDER_H  <freetype/ftrender.h>
+#define FT_RENDER_H  <ftrender.h>
 
 
   /*************************************************************************
@@ -325,7 +325,7 @@
    *   structures and macros related to the auto-hinting module.
    *
    */
-#define FT_AUTOHINTER_H  <freetype/ftautoh.h>
+#define FT_AUTOHINTER_H  <ftautoh.h>
 
 
   /*************************************************************************
@@ -338,7 +338,7 @@
    *   structures and macros related to the CFF driver module.
    *
    */
-#define FT_CFF_DRIVER_H  <freetype/ftcffdrv.h>
+#define FT_CFF_DRIVER_H  <ftcffdrv.h>
 
 
   /*************************************************************************
@@ -351,7 +351,7 @@
    *   structures and macros related to the TrueType driver module.
    *
    */
-#define FT_TRUETYPE_DRIVER_H  <freetype/ftttdrv.h>
+#define FT_TRUETYPE_DRIVER_H  <ftttdrv.h>
 
 
   /*************************************************************************
@@ -364,7 +364,7 @@
    *   types and API specific to the Type~1 format.
    *
    */
-#define FT_TYPE1_TABLES_H  <freetype/t1tables.h>
+#define FT_TYPE1_TABLES_H  <t1tables.h>
 
 
   /*************************************************************************
@@ -379,7 +379,7 @@
    *   definitions, taken from the TrueType and OpenType specifications.
    *
    */
-#define FT_TRUETYPE_IDS_H  <freetype/ttnameid.h>
+#define FT_TRUETYPE_IDS_H  <ttnameid.h>
 
 
   /*************************************************************************
@@ -392,7 +392,7 @@
    *   types and API specific to the TrueType (as well as OpenType) format.
    *
    */
-#define FT_TRUETYPE_TABLES_H  <freetype/tttables.h>
+#define FT_TRUETYPE_TABLES_H  <tttables.h>
 
 
   /*************************************************************************
@@ -406,7 +406,7 @@
    *   SFNT-based font formats (i.e., TrueType and OpenType).
    *
    */
-#define FT_TRUETYPE_TAGS_H  <freetype/tttags.h>
+#define FT_TRUETYPE_TAGS_H  <tttags.h>
 
 
   /*************************************************************************
@@ -420,7 +420,7 @@
    *   face.
    *
    */
-#define FT_BDF_H  <freetype/ftbdf.h>
+#define FT_BDF_H  <ftbdf.h>
 
 
   /*************************************************************************
@@ -434,7 +434,7 @@
    *   face.
    *
    */
-#define FT_CID_H  <freetype/ftcid.h>
+#define FT_CID_H  <ftcid.h>
 
 
   /*************************************************************************
@@ -447,7 +447,7 @@
    *   definitions of an API which supports gzip-compressed files.
    *
    */
-#define FT_GZIP_H  <freetype/ftgzip.h>
+#define FT_GZIP_H  <ftgzip.h>
 
 
   /*************************************************************************
@@ -460,7 +460,7 @@
    *   definitions of an API which supports LZW-compressed files.
    *
    */
-#define FT_LZW_H  <freetype/ftlzw.h>
+#define FT_LZW_H  <ftlzw.h>
 
 
   /*************************************************************************
@@ -473,7 +473,7 @@
    *   definitions of an API which supports bzip2-compressed files.
    *
    */
-#define FT_BZIP2_H  <freetype/ftbzip2.h>
+#define FT_BZIP2_H  <ftbzip2.h>
 
 
   /*************************************************************************
@@ -486,7 +486,7 @@
    *   definitions of an API which supports Windows FNT files.
    *
    */
-#define FT_WINFONTS_H   <freetype/ftwinfnt.h>
+#define FT_WINFONTS_H   <ftwinfnt.h>
 
 
   /*************************************************************************
@@ -499,7 +499,7 @@
    *   API of the optional glyph management component.
    *
    */
-#define FT_GLYPH_H  <freetype/ftglyph.h>
+#define FT_GLYPH_H  <ftglyph.h>
 
 
   /*************************************************************************
@@ -512,7 +512,7 @@
    *   API of the optional bitmap conversion component.
    *
    */
-#define FT_BITMAP_H  <freetype/ftbitmap.h>
+#define FT_BITMAP_H  <ftbitmap.h>
 
 
   /*************************************************************************
@@ -525,7 +525,7 @@
    *   API of the optional exact bounding box computation routines.
    *
    */
-#define FT_BBOX_H  <freetype/ftbbox.h>
+#define FT_BBOX_H  <ftbbox.h>
 
 
   /*************************************************************************
@@ -538,7 +538,7 @@
    *   API of the optional FreeType~2 cache sub-system.
    *
    */
-#define FT_CACHE_H  <freetype/ftcache.h>
+#define FT_CACHE_H  <ftcache.h>
 
 
   /*************************************************************************
@@ -612,7 +612,7 @@
    *   compiled on the Mac (note that the base API still works though).
    *
    */
-#define FT_MAC_H  <freetype/ftmac.h>
+#define FT_MAC_H  <ftmac.h>
 
 
   /*************************************************************************
@@ -625,7 +625,7 @@
    *   optional multiple-masters management API of FreeType~2.
    *
    */
-#define FT_MULTIPLE_MASTERS_H  <freetype/ftmm.h>
+#define FT_MULTIPLE_MASTERS_H  <ftmm.h>
 
 
   /*************************************************************************
@@ -639,7 +639,7 @@
    *   SFNT-based font formats (i.e., TrueType and OpenType).
    *
    */
-#define FT_SFNT_NAMES_H  <freetype/ftsnames.h>
+#define FT_SFNT_NAMES_H  <ftsnames.h>
 
 
   /*************************************************************************
@@ -653,7 +653,7 @@
    *   GPOS, GSUB, JSTF).
    *
    */
-#define FT_OPENTYPE_VALIDATE_H  <freetype/ftotval.h>
+#define FT_OPENTYPE_VALIDATE_H  <ftotval.h>
 
 
   /*************************************************************************
@@ -667,7 +667,7 @@
    *   mort, morx, bsln, just, kern, opbd, trak, prop).
    *
    */
-#define FT_GX_VALIDATE_H  <freetype/ftgxval.h>
+#define FT_GX_VALIDATE_H  <ftgxval.h>
 
 
   /*************************************************************************
@@ -680,7 +680,7 @@
    *   FreeType~2 API which accesses PFR-specific data.
    *
    */
-#define FT_PFR_H  <freetype/ftpfr.h>
+#define FT_PFR_H  <ftpfr.h>
 
 
   /*************************************************************************
@@ -692,7 +692,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which provides functions to stroke outline paths.
    */
-#define FT_STROKER_H  <freetype/ftstroke.h>
+#define FT_STROKER_H  <ftstroke.h>
 
 
   /*************************************************************************
@@ -704,7 +704,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which performs artificial obliquing and emboldening.
    */
-#define FT_SYNTHESIS_H  <freetype/ftsynth.h>
+#define FT_SYNTHESIS_H  <ftsynth.h>
 
 
   /*************************************************************************
@@ -717,7 +717,7 @@
    *   FreeType~2 API which provides functions specific to the XFree86 and
    *   X.Org X11 servers.
    */
-#define FT_XFREE86_H  <freetype/ftxf86.h>
+#define FT_XFREE86_H  <ftxf86.h>
 
 
   /*************************************************************************
@@ -730,7 +730,7 @@
    *   FreeType~2 API which performs trigonometric computations (e.g.,
    *   cosines and arc tangents).
    */
-#define FT_TRIGONOMETRY_H  <freetype/fttrigon.h>
+#define FT_TRIGONOMETRY_H  <fttrigon.h>
 
 
   /*************************************************************************
@@ -742,7 +742,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which performs color filtering for subpixel rendering.
    */
-#define FT_LCD_FILTER_H  <freetype/ftlcdfil.h>
+#define FT_LCD_FILTER_H  <ftlcdfil.h>
 
 
   /*************************************************************************
@@ -754,7 +754,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which performs color filtering for subpixel rendering.
    */
-#define FT_UNPATENTED_HINTING_H  <freetype/ttunpat.h>
+#define FT_UNPATENTED_HINTING_H  <ttunpat.h>
 
 
   /*************************************************************************
@@ -766,7 +766,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which performs color filtering for subpixel rendering.
    */
-#define FT_INCREMENTAL_H  <freetype/ftincrem.h>
+#define FT_INCREMENTAL_H  <ftincrem.h>
 
 
   /*************************************************************************
@@ -778,7 +778,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which returns entries from the TrueType GASP table.
    */
-#define FT_GASP_H  <freetype/ftgasp.h>
+#define FT_GASP_H  <ftgasp.h>
 
 
   /*************************************************************************
@@ -790,38 +790,38 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which returns individual and ranged glyph advances.
    */
-#define FT_ADVANCES_H  <freetype/ftadvanc.h>
+#define FT_ADVANCES_H  <ftadvanc.h>
 
 
   /* */
 
-#define FT_ERROR_DEFINITIONS_H  <freetype/fterrdef.h>
+#define FT_ERROR_DEFINITIONS_H  <fterrdef.h>
 
 
   /* The internals of the cache sub-system are no longer exposed.  We */
   /* default to FT_CACHE_H at the moment just in case, but we know of */
   /* no rogue client that uses them.                                  */
   /*                                                                  */
-#define FT_CACHE_MANAGER_H           <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_MRU_H      <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_MANAGER_H  <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_CACHE_H    <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_GLYPH_H    <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_IMAGE_H    <freetype/ftcache.h>
-#define FT_CACHE_INTERNAL_SBITS_H    <freetype/ftcache.h>
+#define FT_CACHE_MANAGER_H           <ftcache.h>
+#define FT_CACHE_INTERNAL_MRU_H      <ftcache.h>
+#define FT_CACHE_INTERNAL_MANAGER_H  <ftcache.h>
+#define FT_CACHE_INTERNAL_CACHE_H    <ftcache.h>
+#define FT_CACHE_INTERNAL_GLYPH_H    <ftcache.h>
+#define FT_CACHE_INTERNAL_IMAGE_H    <ftcache.h>
+#define FT_CACHE_INTERNAL_SBITS_H    <ftcache.h>
 
 
-#define FT_INCREMENTAL_H          <freetype/ftincrem.h>
+#define FT_INCREMENTAL_H          <ftincrem.h>
 
-#define FT_TRUETYPE_UNPATENTED_H  <freetype/ttunpat.h>
+#define FT_TRUETYPE_UNPATENTED_H  <ttunpat.h>
 
 
   /*
-   * Include internal headers definitions from <freetype/internal/...>
+   * Include internal headers definitions from <internal/...>
    * only when building the library.
    */
 #ifdef FT2_BUILD_LIBRARY
-#define  FT_INTERNAL_INTERNAL_H  <freetype/internal/internal.h>
+#define  FT_INTERNAL_INTERNAL_H  <internal/internal.h>
 #include FT_INTERNAL_INTERNAL_H
 #endif /* FT2_BUILD_LIBRARY */
 
diff --git a/include/freetype/config/ftmodule.h b/include/config/ftmodule.h
similarity index 100%
rename from include/freetype/config/ftmodule.h
rename to include/config/ftmodule.h
diff --git a/include/freetype/config/ftoption.h b/include/config/ftoption.h
similarity index 98%
rename from include/freetype/config/ftoption.h
rename to include/config/ftoption.h
index bc239bf..72cc060 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/config/ftoption.h
@@ -38,9 +38,9 @@
   /*    library from a single source directory.                            */
   /*                                                                       */
   /*  - You can put a copy of this file in your build directory, more      */
-  /*    precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD'   */
-  /*    is the name of a directory that is included _before_ the FreeType  */
-  /*    include path during compilation.                                   */
+  /*    precisely in `$BUILD/config/ftoption.h', where `$BUILD' is the     */
+  /*    name of a directory that is included _before_ the FreeType include */
+  /*    path during compilation.                                           */
   /*                                                                       */
   /*    The default FreeType Makefiles and Jamfiles use the build          */
   /*    directory `builds/<system>' by default, but you can easily change  */
@@ -51,7 +51,7 @@
   /*    locate this file during the build.  For example,                   */
   /*                                                                       */
   /*      #define FT_CONFIG_OPTIONS_H  <myftoptions.h>                     */
-  /*      #include <freetype/config/ftheader.h>                            */
+  /*      #include <config/ftheader.h>                                     */
   /*                                                                       */
   /*    will use `$BUILD/myftoptions.h' instead of this file for macro     */
   /*    definitions.                                                       */
@@ -59,7 +59,7 @@
   /*    Note also that you can similarly pre-define the macro              */
   /*    FT_CONFIG_MODULES_H used to locate the file listing of the modules */
   /*    that are statically linked to the library at compile time.  By     */
-  /*    default, this file is <freetype/config/ftmodule.h>.                */
+  /*    default, this file is <config/ftmodule.h>.                         */
   /*                                                                       */
   /*  We highly recommend using the third method whenever possible.        */
   /*                                                                       */
@@ -528,7 +528,7 @@
   /* does not contain any glyph name though.                               */
   /*                                                                       */
   /* Accessing SFNT names is done through the functions declared in        */
-  /* `freetype/ftsnames.h'.                                                */
+  /* `ftsnames.h'.                                                         */
   /*                                                                       */
 #define TT_CONFIG_OPTION_SFNT_NAMES
 
@@ -569,7 +569,7 @@
   /*   Do not #undef this macro here, since the build system might         */
   /*   define it for certain configurations only.                          */
   /*                                                                       */
-/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
 
   /*************************************************************************/
@@ -641,7 +641,7 @@
   /*     ...                                                               */
   /*   }                                                                   */
   /*                                                                       */
-#define TT_CONFIG_OPTION_UNPATENTED_HINTING
+/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */
 
 
   /*************************************************************************/
diff --git a/include/freetype/config/ftstdlib.h b/include/config/ftstdlib.h
similarity index 100%
rename from include/freetype/config/ftstdlib.h
rename to include/config/ftstdlib.h
diff --git a/include/freetype/freetype.h b/include/freetype.h
similarity index 96%
rename from include/freetype/freetype.h
rename to include/freetype.h
index 0d5680b..372319a 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype.h
@@ -42,6 +42,38 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Section>                                                             */
+  /*    header_inclusion                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    FreeType's header inclusion scheme                                 */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How client applications should include FreeType header files.      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    To be as flexible as possible (and for historical reasons),        */
+  /*    FreeType uses a very special inclusion scheme to load header       */
+  /*    files, for example                                                 */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      #include <ft2build.h>                                            */
+  /*                                                                       */
+  /*      #include FT_FREETYPE_H                                           */
+  /*      #include FT_OUTLINE_H                                            */
+  /*    }                                                                  */
+  /*                                                                       */
+  /*    A compiler and its preprocessor only needs an include path to find */
+  /*    the file `ft2build.h'; the exact locations and names of the other  */
+  /*    FreeType header files are hidden by preprocessor macro names,      */
+  /*    loaded by `ft2build.h'.  The API documentation always gives the    */
+  /*    header macro name needed for a particular function.                */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
   /*    user_allocation                                                    */
   /*                                                                       */
   /* <Title>                                                               */
@@ -98,7 +130,10 @@
   /*    FT_FACE_FLAG_FIXED_WIDTH                                           */
   /*    FT_FACE_FLAG_HORIZONTAL                                            */
   /*    FT_FACE_FLAG_VERTICAL                                              */
+  /*    FT_FACE_FLAG_COLOR                                                 */
   /*    FT_FACE_FLAG_SFNT                                                  */
+  /*    FT_FACE_FLAG_CID_KEYED                                             */
+  /*    FT_FACE_FLAG_TRICKY                                                */
   /*    FT_FACE_FLAG_KERNING                                               */
   /*    FT_FACE_FLAG_MULTIPLE_MASTERS                                      */
   /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
@@ -329,12 +364,14 @@
   /*    It also embeds a memory manager (see @FT_Memory), as well as a     */
   /*    scan-line converter object (see @FT_Raster).                       */
   /*                                                                       */
-  /*    For multi-threading applications each thread should have its own   */
-  /*    FT_Library object.                                                 */
+  /*    In multi-threaded applications, make sure that the same FT_Library */
+  /*    object or any of its children doesn't get accessed in parallel.    */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Library objects are normally created by @FT_Init_FreeType, and     */
-  /*    destroyed with @FT_Done_FreeType.                                  */
+  /*    destroyed with @FT_Done_FreeType.  If you need reference-counting  */
+  /*    (cf. @FT_Reference_Library), use @FT_New_Library and               */
+  /*    @FT_Done_Library.                                                  */
   /*                                                                       */
   typedef struct FT_LibraryRec_  *FT_Library;
 
@@ -415,7 +452,8 @@
   /* <Note>                                                                */
   /*    Each @FT_Face has an _active_ @FT_Size object that is used by      */
   /*    functions like @FT_Load_Glyph to determine the scaling             */
-  /*    transformation which is used to load and hint glyphs and metrics.  */
+  /*    transformation that in turn is used to load and hint glyphs and    */
+  /*    metrics.                                                           */
   /*                                                                       */
   /*    You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes,                */
   /*    @FT_Request_Size or even @FT_Select_Size to change the content     */
@@ -550,11 +588,12 @@
   /*    FT_ENCODING_MS_SYMBOL ::                                           */
   /*      Corresponds to the Microsoft Symbol encoding, used to encode     */
   /*      mathematical symbols in the 32..255 character code range.  For   */
-  /*      more information, see `http://www.ceviz.net/symbol.htm'.         */
+  /*      more information, see                                            */
+  /*      `http://www.kostis.net/charsets/symbol.htm'.                     */
   /*                                                                       */
   /*    FT_ENCODING_SJIS ::                                                */
   /*      Corresponds to Japanese SJIS encoding.  More info at             */
-  /*      at `http://langsupport.japanreference.com/encoding.shtml'.       */
+  /*      at `http://en.wikipedia.org/wiki/Shift_JIS'.                     */
   /*      See note on multi-byte encodings below.                          */
   /*                                                                       */
   /*    FT_ENCODING_GB2312 ::                                              */
@@ -568,7 +607,7 @@
   /*    FT_ENCODING_WANSUNG ::                                             */
   /*      Corresponds to the Korean encoding system known as Wansung.      */
   /*      For more information see                                         */
-  /*      `http://www.microsoft.com/typography/unicode/949.txt'.           */
+  /*      `http://msdn.microsoft.com/en-US/goglobal/cc305154'.             */
   /*                                                                       */
   /*    FT_ENCODING_JOHAB ::                                               */
   /*      The Korean standard character set (KS~C 5601-1992), which        */
@@ -643,10 +682,10 @@
   /*    FT_ENCODING_APPLE_ROMAN).                                          */
   /*                                                                       */
   /*    If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function       */
-  /*    @FT_Get_CMap_Language_ID  to query the Mac language ID which may   */
+  /*    @FT_Get_CMap_Language_ID to query the Mac language ID that may     */
   /*    be needed to be able to distinguish Apple encoding variants.  See  */
   /*                                                                       */
-  /*      http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT  */
+  /*      http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt  */
   /*                                                                       */
   /*    to get an idea how to do that.  Basically, if the language ID      */
   /*    is~0, don't use it, otherwise subtract 1 from the language ID.     */
@@ -806,7 +845,7 @@
   /*                           highest CID used in the font.               */
   /*                                                                       */
   /*    family_name         :: The face's family name.  This is an ASCII   */
-  /*                           string, usually in English, which describes */
+  /*                           string, usually in English, that describes  */
   /*                           the typeface's family (like `Times New      */
   /*                           Roman', `Bodoni', `Garamond', etc).  This   */
   /*                           is a least common denominator used to list  */
@@ -818,7 +857,7 @@
   /*                           PDF file).                                  */
   /*                                                                       */
   /*    style_name          :: The face's style name.  This is an ASCII    */
-  /*                           string, usually in English, which describes */
+  /*                           string, usually in English, that describes  */
   /*                           the typeface's style (like `Italic',        */
   /*                           `Bold', `Condensed', etc).  Not all font    */
   /*                           formats provide a style name, so this field */
@@ -1052,7 +1091,7 @@
   /*      exist make FT_Load_Glyph return successfully; in all other cases */
   /*      you get an `FT_Err_Invalid_Argument' error.                      */
   /*                                                                       */
-  /*      Note that CID-keyed fonts which are in an SFNT wrapper don't     */
+  /*      Note that CID-keyed fonts that are in an SFNT wrapper don't      */
   /*      have this flag set since the glyphs are accessed in the normal   */
   /*      way (using contiguous indices); the `CID-ness' isn't visible to  */
   /*      the application.                                                 */
@@ -1060,7 +1099,7 @@
   /*    FT_FACE_FLAG_TRICKY ::                                             */
   /*      Set if the font is `tricky', this is, it always needs the        */
   /*      font format's native hinting engine to get a reasonable result.  */
-  /*      A typical example is the Chinese font `mingli.ttf' which uses    */
+  /*      A typical example is the Chinese font `mingli.ttf' that uses     */
   /*      TrueType bytecode instructions to move and scale all of its      */
   /*      subglyphs.                                                       */
   /*                                                                       */
@@ -1073,6 +1112,10 @@
   /*      Currently, there are about a dozen TrueType fonts in the list of */
   /*      tricky fonts; they are hard-coded in file `ttobjs.c'.            */
   /*                                                                       */
+  /*    FT_FACE_FLAG_COLOR ::                                              */
+  /*      Set if the font has color glyph tables.  To access color glyphs  */
+  /*      use @FT_LOAD_COLOR.                                              */
+  /*                                                                       */
 #define FT_FACE_FLAG_SCALABLE          ( 1L <<  0 )
 #define FT_FACE_FLAG_FIXED_SIZES       ( 1L <<  1 )
 #define FT_FACE_FLAG_FIXED_WIDTH       ( 1L <<  2 )
@@ -1087,6 +1130,7 @@
 #define FT_FACE_FLAG_HINTER            ( 1L << 11 )
 #define FT_FACE_FLAG_CID_KEYED         ( 1L << 12 )
 #define FT_FACE_FLAG_TRICKY            ( 1L << 13 )
+#define FT_FACE_FLAG_COLOR             ( 1L << 14 )
 
 
   /*************************************************************************
@@ -1271,6 +1315,20 @@
           ( face->face_flags & FT_FACE_FLAG_TRICKY )
 
 
+  /*************************************************************************
+   *
+   * @macro:
+   *   FT_HAS_COLOR( face )
+   *
+   * @description:
+   *   A macro that returns true whenever a face object contains
+   *   tables for color glyphs.
+   *
+   */
+#define FT_HAS_COLOR( face ) \
+          ( face->face_flags & FT_FACE_FLAG_COLOR )
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Const>                                                               */
@@ -1392,9 +1450,9 @@
   /* <Fields>                                                              */
   /*    face    :: Handle to the parent face object.                       */
   /*                                                                       */
-  /*    generic :: A typeless pointer, which is unused by the FreeType     */
-  /*               library or any of its drivers.  It can be used by       */
-  /*               client applications to link their own data to each size */
+  /*    generic :: A typeless pointer, unused by the FreeType library or   */
+  /*               any of its drivers.  It can be used by client           */
+  /*               applications to link their own data to each size        */
   /*               object.                                                 */
   /*                                                                       */
   /*    metrics :: Metrics for this size object.  This field is read-only. */
@@ -1462,10 +1520,10 @@
   /*                         listed through a direct, single-linked list   */
   /*                         using its `next' field.                       */
   /*                                                                       */
-  /*    generic           :: A typeless pointer which is unused by the     */
-  /*                         FreeType library or any of its drivers.  It   */
-  /*                         can be used by client applications to link    */
-  /*                         their own data to each glyph slot object.     */
+  /*    generic           :: A typeless pointer unused by the FreeType     */
+  /*                         library or any of its drivers.  It can be     */
+  /*                         used by client applications to link their own */
+  /*                         data to each glyph slot object.               */
   /*                                                                       */
   /*    metrics           :: The metrics of the last loaded glyph in the   */
   /*                         slot.  The returned values depend on the last */
@@ -1492,8 +1550,8 @@
   /*                                                                       */
   /*    advance           :: This shorthand is, depending on               */
   /*                         @FT_LOAD_IGNORE_TRANSFORM, the transformed    */
-  /*                         advance width for the glyph (in 26.6          */
-  /*                         fractional pixel format).  As specified with  */
+  /*                         (hinted) advance width for the glyph, in 26.6 */
+  /*                         fractional pixel format.  As specified with   */
   /*                         @FT_LOAD_VERTICAL_LAYOUT, it uses either the  */
   /*                         `horiAdvance' or the `vertAdvance' value of   */
   /*                         `metrics' field.                              */
@@ -1582,7 +1640,7 @@
   /*    `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP.         */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    Here a small pseudo code fragment which shows how to use           */
+  /*    Here a small pseudo code fragment that shows how to use            */
   /*    `lsb_delta' and `rsb_delta':                                       */
   /*                                                                       */
   /*    {                                                                  */
@@ -1678,6 +1736,9 @@
   /*    For multi-threading applications each thread should have its own   */
   /*    FT_Library object.                                                 */
   /*                                                                       */
+  /*    If you need reference-counting (cf. @FT_Reference_Library), use    */
+  /*    @FT_New_Library and @FT_Done_Library.                              */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Init_FreeType( FT_Library  *alibrary );
 
@@ -1808,7 +1869,7 @@
   /*                   opening a new face.                                 */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    The stream type is determined by the contents of `flags' which     */
+  /*    The stream type is determined by the contents of `flags' that      */
   /*    are tested in the following order by @FT_Open_Face:                */
   /*                                                                       */
   /*    If the `FT_OPEN_MEMORY' bit is set, assume that this is a          */
@@ -1872,6 +1933,10 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    Use @FT_Done_Face to destroy the created @FT_Face object (along    */
+  /*    with its slot and sizes).                                          */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_New_Face( FT_Library   library,
                const char*  filepathname,
@@ -1885,7 +1950,7 @@
   /*    FT_New_Memory_Face                                                 */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This function calls @FT_Open_Face to open a font which has been    */
+  /*    This function calls @FT_Open_Face to open a font that has been     */
   /*    loaded into memory.                                                */
   /*                                                                       */
   /* <InOut>                                                               */
@@ -1931,7 +1996,7 @@
   /*    library    :: A handle to the library resource.                    */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    args       :: A pointer to an `FT_Open_Args' structure which must  */
+  /*    args       :: A pointer to an `FT_Open_Args' structure that must   */
   /*                  be filled by the caller.                             */
   /*                                                                       */
   /*    face_index :: The index of the face within the font.  The first    */
@@ -1947,7 +2012,7 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
-  /*    slot for the face object which can be accessed directly through    */
+  /*    slot for the face object that can be accessed directly through     */
   /*    `face->glyph'.                                                     */
   /*                                                                       */
   /*    FT_Open_Face can be used to quickly check whether the font         */
@@ -1956,7 +2021,7 @@
   /*    if the font format is recognized, or non-zero otherwise;           */
   /*    the function returns a more or less empty face handle in `*aface'  */
   /*    (if `aface' isn't NULL).  The only useful field in this special    */
-  /*    case is `face->num_faces' which gives the number of faces within   */
+  /*    case is `face->num_faces' that gives the number of faces within    */
   /*    the font file.  After examination, the returned @FT_Face structure */
   /*    should be deallocated with a call to @FT_Done_Face.                */
   /*                                                                       */
@@ -2014,7 +2079,7 @@
   /*    face       :: The target face object.                              */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    parameters :: A pointer to @FT_Open_Args which must be filled by   */
+  /*    parameters :: A pointer to @FT_Open_Args that must be filled by    */
   /*                  the caller.                                          */
   /*                                                                       */
   /* <Return>                                                              */
@@ -2045,7 +2110,7 @@
   /*    then only destroys a face if the counter is~1, otherwise it simply */
   /*    decrements the counter.                                            */
   /*                                                                       */
-  /*    This function helps in managing life-cycles of structures which    */
+  /*    This function helps in managing life-cycles of structures that     */
   /*    reference @FT_Face objects.                                        */
   /*                                                                       */
   /* <Input>                                                               */
@@ -2352,7 +2417,7 @@
   /*    the details.                                                       */
   /*                                                                       */
   /*    For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is        */
-  /*    returned for invalid CID values (this is, for CID values which     */
+  /*    returned for invalid CID values (this is, for CID values that      */
   /*    don't have a corresponding glyph in the font).  See the discussion */
   /*    of the @FT_FACE_FLAG_CID_KEYED flag for more details.              */
   /*                                                                       */
@@ -2626,7 +2691,7 @@
    *   `load_flags'.  They can't be ORed.
    *
    *   If @FT_LOAD_RENDER is also set, the glyph is rendered in the
-   *   corresponding mode (i.e., the mode which matches the used algorithm
+   *   corresponding mode (i.e., the mode that matches the used algorithm
    *   best).  An exeption is FT_LOAD_TARGET_MONO since it implies
    *   @FT_LOAD_MONOCHROME.
    *
@@ -2994,7 +3059,7 @@
   /*                                                                       */
   /*    This function is not compiled within the library if the config     */
   /*    macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in              */
-  /*    `include/freetype/config/ftoptions.h'.                             */
+  /*    `ftoptions.h'.                                                     */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Get_Glyph_Name( FT_Face     face,
@@ -3050,8 +3115,8 @@
   /*                                                                       */
   /*    Because many fonts contain more than a single cmap for Unicode     */
   /*    encoding, this function has some special code to select the one    */
-  /*    which covers Unicode best (`best' in the sense that a UCS-4 cmap   */
-  /*    is preferred to a UCS-2 cmap).  It is thus preferable to           */
+  /*    that covers Unicode best (`best' in the sense that a UCS-4 cmap is */
+  /*    preferred to a UCS-2 cmap).  It is thus preferable to              */
   /*    @FT_Set_Charmap in this case.                                      */
   /*                                                                       */
   FT_EXPORT( FT_Error )
@@ -3405,7 +3470,7 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    Use this function rather than directly reading the `fs_type' field */
-  /*    in the @PS_FontInfoRec structure which is only guaranteed to       */
+  /*    in the @PS_FontInfoRec structure, which is only guaranteed to      */
   /*    return the correct results for Type~1 fonts.                       */
   /*                                                                       */
   /* <Since>                                                               */
@@ -3585,7 +3650,7 @@
   /*      The character codepoint in Unicode.                              */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    A pointer to an array of variant selector code points which are    */
+  /*    A pointer to an array of variant selector code points that are     */
   /*    active for the given character, or NULL if the corresponding list  */
   /*    is empty.                                                          */
   /*                                                                       */
@@ -3619,7 +3684,7 @@
   /*      The variant selector code point in Unicode.                      */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    A list of all the code points which are specified by this selector */
+  /*    A list of all the code points that are specified by this selector  */
   /*    (both default and non-default codes are returned) or NULL if there */
   /*    is no valid cmap or the variant selector is invalid.               */
   /*                                                                       */
@@ -3891,8 +3956,8 @@
    *
    */
 #define FREETYPE_MAJOR  2
-#define FREETYPE_MINOR  4
-#define FREETYPE_PATCH  12
+#define FREETYPE_MINOR  5
+#define FREETYPE_PATCH  2
 
 
   /*************************************************************************/
diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h
deleted file mode 100644
index ccbcbcc..0000000
--- a/include/freetype/ftcffdrv.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  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/internal/internal.h b/include/freetype/internal/internal.h
deleted file mode 100644
index f500a65..0000000
--- a/include/freetype/internal/internal.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  internal.h                                                             */
-/*                                                                         */
-/*    Internal header files (specification only).                          */
-/*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This file is automatically included by `ft2build.h'.                  */
-  /* Do not include it manually!                                           */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#define FT_INTERNAL_OBJECTS_H             <freetype/internal/ftobjs.h>
-#define FT_INTERNAL_PIC_H                 <freetype/internal/ftpic.h>
-#define FT_INTERNAL_STREAM_H              <freetype/internal/ftstream.h>
-#define FT_INTERNAL_MEMORY_H              <freetype/internal/ftmemory.h>
-#define FT_INTERNAL_DEBUG_H               <freetype/internal/ftdebug.h>
-#define FT_INTERNAL_CALC_H                <freetype/internal/ftcalc.h>
-#define FT_INTERNAL_DRIVER_H              <freetype/internal/ftdriver.h>
-#define FT_INTERNAL_TRACE_H               <freetype/internal/fttrace.h>
-#define FT_INTERNAL_GLYPH_LOADER_H        <freetype/internal/ftgloadr.h>
-#define FT_INTERNAL_SFNT_H                <freetype/internal/sfnt.h>
-#define FT_INTERNAL_SERVICE_H             <freetype/internal/ftserv.h>
-#define FT_INTERNAL_RFORK_H               <freetype/internal/ftrfork.h>
-#define FT_INTERNAL_VALIDATE_H            <freetype/internal/ftvalid.h>
-
-#define FT_INTERNAL_TRUETYPE_TYPES_H      <freetype/internal/tttypes.h>
-#define FT_INTERNAL_TYPE1_TYPES_H         <freetype/internal/t1types.h>
-
-#define FT_INTERNAL_POSTSCRIPT_AUX_H      <freetype/internal/psaux.h>
-#define FT_INTERNAL_POSTSCRIPT_HINTS_H    <freetype/internal/pshints.h>
-#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H  <freetype/internal/psglobal.h>
-
-#define FT_INTERNAL_AUTOHINT_H            <freetype/internal/autohint.h>
-
-
-/* END */
diff --git a/include/freetype/internal/pcftypes.h b/include/freetype/internal/pcftypes.h
deleted file mode 100644
index 382796f..0000000
--- a/include/freetype/internal/pcftypes.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  pcftypes.h
-
-  FreeType font driver for pcf fonts
-
-  Copyright (C) 2000, 2001, 2002 by
-  Francesco Zappa Nardelli
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-
-#ifndef __PCFTYPES_H__
-#define __PCFTYPES_H__
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-
-FT_BEGIN_HEADER
-
-
-  typedef struct  PCF_Public_FaceRec_
-  {
-    FT_FaceRec    root;
-    FT_StreamRec  gzip_stream;
-    FT_Stream     gzip_source;
-
-    char*         charset_encoding;
-    char*         charset_registry;
-
-  } PCF_Public_FaceRec, *PCF_Public_Face;
-
-
-FT_END_HEADER
-
-#endif  /* __PCFTYPES_H__ */
-
-
-/* END */
diff --git a/include/ft2build.h b/include/ft2build.h
index 923d887..6f8eb7f 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -3,9 +3,8 @@
 /*  ft2build.h                                                             */
 /*                                                                         */
 /*    FreeType 2 build and setup macros.                                   */
-/*    (Generic version)                                                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2006 by                                           */
+/*  Copyright 1996-2001, 2006, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,21 +18,25 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* This file corresponds to the default `ft2build.h' file for            */
-  /* FreeType 2.  It uses the `freetype' include root.                     */
+  /* This is the `entry point' for FreeType header file inclusions.  It is */
+  /* the only header file which should be included directly; all other     */
+  /* FreeType header files should be accessed with macro names (after      */
+  /* including `ft2build.h').                                              */
   /*                                                                       */
-  /* Note that specific platforms might use a different configuration.     */
-  /* See builds/unix/ft2unix.h for an example.                             */
+  /* A typical example is                                                  */
+  /*                                                                       */
+  /*   #include <ft2build.h>                                               */
+  /*   #include FT_FREETYPE_H                                              */
   /*                                                                       */
   /*************************************************************************/
 
 
-#ifndef __FT2_BUILD_GENERIC_H__
-#define __FT2_BUILD_GENERIC_H__
+#ifndef __FT2BUILD_H__
+#define __FT2BUILD_H__
 
-#include <freetype/config/ftheader.h>
+#include <config/ftheader.h>
 
-#endif /* __FT2_BUILD_GENERIC_H__ */
+#endif /* __FT2BUILD_H__ */
 
 
 /* END */
diff --git a/include/freetype/ftadvanc.h b/include/ftadvanc.h
similarity index 98%
rename from include/freetype/ftadvanc.h
rename to include/ftadvanc.h
index 012b74b..8f7e2fc 100644
--- a/include/freetype/ftadvanc.h
+++ b/include/ftadvanc.h
@@ -64,11 +64,11 @@
   /*    corresponding hinting mode or font driver doesn't allow for very   */
   /*    quick advance computation.                                         */
   /*                                                                       */
-  /*    Typically, glyphs which are either unscaled, unhinted, bitmapped,  */
+  /*    Typically, glyphs that are either unscaled, unhinted, bitmapped,   */
   /*    or light-hinted can have their advance width computed very         */
   /*    quickly.                                                           */
   /*                                                                       */
-  /*    Normal and bytecode hinted modes, which require loading, scaling,  */
+  /*    Normal and bytecode hinted modes that require loading, scaling,    */
   /*    and hinting of the glyph outline, are extremely slow by            */
   /*    comparison.                                                        */
   /*                                                                       */
diff --git a/include/freetype/ftautoh.h b/include/ftautoh.h
similarity index 97%
rename from include/freetype/ftautoh.h
rename to include/ftautoh.h
index 62ce96d..bf97b3f 100644
--- a/include/freetype/ftautoh.h
+++ b/include/ftautoh.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for controlling the auto-hinter (specification only).   */
 /*                                                                         */
-/*  Copyright 2012 by                                                      */
+/*  Copyright 2012, 2013 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -61,6 +61,8 @@
    *   glyph-to-script-map
    *
    * @description:
+   *   *Experimental* *only*
+   *
    *   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
@@ -77,7 +79,7 @@
    *   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
+   *   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.
@@ -113,6 +115,8 @@
    *   FT_AUTOHINTER_SCRIPT_XXX
    *
    * @description:
+   *   *Experimental* *only*
+   *
    *   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.
@@ -236,6 +240,8 @@
    *   FT_Prop_GlyphToScriptMap
    *
    * @description:
+   *   *Experimental* *only*
+   *
    *   The data exchange structure for the @glyph-to-script-map property.
    *
    */
@@ -253,6 +259,8 @@
    *   fallback-script
    *
    * @description:
+   *   *Experimental* *only*
+   *
    *   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
@@ -274,7 +282,7 @@
    *   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
+   *   creation of the glyph-to-script map that 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
diff --git a/include/freetype/ftbbox.h b/include/ftbbox.h
similarity index 96%
rename from include/freetype/ftbbox.h
rename to include/ftbbox.h
index 9766919..8938841 100644
--- a/include/freetype/ftbbox.h
+++ b/include/ftbbox.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType exact bbox computation (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2007, 2011 by                               */
+/*  Copyright 1996-2001, 2003, 2007, 2011, 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 @@
   /* <Description>                                                         */
   /*    Compute the exact bounding box of an outline.  This is slower      */
   /*    than computing the control box.  However, it uses an advanced      */
-  /*    algorithm which returns _very_ quickly when the two boxes          */
+  /*    algorithm that returns _very_ quickly when the two boxes           */
   /*    coincide.  Otherwise, the outline Bézier arcs are traversed to     */
   /*    extract their extrema.                                             */
   /*                                                                       */
@@ -78,7 +78,7 @@
   /*    @FT_LOAD_NO_SCALE, the resulting BBox is meaningless.  To get      */
   /*    reasonable values for the BBox it is necessary to load the glyph   */
   /*    at a large ppem value (so that the hinting instructions can        */
-  /*    properly shift and scale the subglyphs), then extracting the BBox  */
+  /*    properly shift and scale the subglyphs), then extracting the BBox, */
   /*    which can be eventually converted back to font units.              */
   /*                                                                       */
   FT_EXPORT( FT_Error )
diff --git a/include/freetype/ftbdf.h b/include/ftbdf.h
similarity index 100%
rename from include/freetype/ftbdf.h
rename to include/ftbdf.h
diff --git a/include/freetype/ftbitmap.h b/include/ftbitmap.h
similarity index 100%
rename from include/freetype/ftbitmap.h
rename to include/ftbitmap.h
diff --git a/include/freetype/ftgzip.h b/include/ftbzip2.h
similarity index 73%
copy from include/freetype/ftgzip.h
copy to include/ftbzip2.h
index acbc4f0..1bf81b1 100644
--- a/include/freetype/ftgzip.h
+++ b/include/ftbzip2.h
@@ -1,11 +1,11 @@
 /***************************************************************************/
 /*                                                                         */
-/*  ftgzip.h                                                               */
+/*  ftbzip2.h                                                              */
 /*                                                                         */
-/*    Gzip-compressed stream support.                                      */
+/*    Bzip2-compressed stream support.                                     */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2006 by                                    */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*  Copyright 2010 by                                                      */
+/*  Joel Klinghed.                                                         */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTGZIP_H__
-#define __FTGZIP_H__
+#ifndef __FTBZIP2_H__
+#define __FTBZIP2_H__
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -34,16 +34,16 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Section>                                                             */
-  /*    gzip                                                               */
+  /*    bzip2                                                              */
   /*                                                                       */
   /* <Title>                                                               */
-  /*    GZIP Streams                                                       */
+  /*    BZIP2 Streams                                                      */
   /*                                                                       */
   /* <Abstract>                                                            */
-  /*    Using gzip-compressed font files.                                  */
+  /*    Using bzip2-compressed font files.                                 */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This section contains the declaration of Gzip-specific functions.  */
+  /*    This section contains the declaration of Bzip2-specific functions. */
   /*                                                                       */
   /*************************************************************************/
 
@@ -51,11 +51,11 @@
  /************************************************************************
   *
   * @function:
-  *   FT_Stream_OpenGzip
+  *   FT_Stream_OpenBzip2
   *
   * @description:
-  *   Open a new stream to parse gzip-compressed font files.  This is
-  *   mainly used to support the compressed `*.pcf.gz' fonts that come
+  *   Open a new stream to parse bzip2-compressed font files.  This is
+  *   mainly used to support the compressed `*.pcf.bz2' fonts that come
   *   with XFree86.
   *
   * @input:
@@ -78,25 +78,25 @@
   *   The stream implementation is very basic and resets the decompression
   *   process each time seeking backwards is needed within the stream.
   *
-  *   In certain builds of the library, gzip compression recognition is
+  *   In certain builds of the library, bzip2 compression recognition is
   *   automatically handled when calling @FT_New_Face or @FT_Open_Face.
   *   This means that if no font driver is capable of handling the raw
-  *   compressed file, the library will try to open a gzipped stream from
-  *   it and re-open the face with it.
+  *   compressed file, the library will try to open a bzip2 compressed stream
+  *   from it and re-open the face with it.
   *
   *   This function may return `FT_Err_Unimplemented_Feature' if your build
-  *   of FreeType was not compiled with zlib support.
+  *   of FreeType was not compiled with bzip2 support.
   */
   FT_EXPORT( FT_Error )
-  FT_Stream_OpenGzip( FT_Stream  stream,
-                      FT_Stream  source );
+  FT_Stream_OpenBzip2( FT_Stream  stream,
+                       FT_Stream  source );
 
  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTGZIP_H__ */
+#endif /* __FTBZIP2_H__ */
 
 
 /* END */
diff --git a/include/freetype/ftcache.h b/include/ftcache.h
similarity index 99%
rename from include/freetype/ftcache.h
rename to include/ftcache.h
index 4ec9587..a5d7100 100644
--- a/include/freetype/ftcache.h
+++ b/include/ftcache.h
@@ -156,7 +156,7 @@
    * @note:
    *   Never use NULL as a valid @FTC_FaceID.
    *
-   *   Face IDs are passed by the client to the cache manager, which calls,
+   *   Face IDs are passed by the client to the cache manager that calls,
    *   when needed, the @FTC_Face_Requester to translate them into new
    *   @FT_Face objects.
    *
diff --git a/include/ftcffdrv.h b/include/ftcffdrv.h
new file mode 100644
index 0000000..e4d039d
--- /dev/null
+++ b/include/ftcffdrv.h
@@ -0,0 +1,254 @@
+/***************************************************************************/
+/*                                                                         */
+/*  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 list below gives the available properties
+   *   together with the necessary macros and structures.
+   *
+   *   The CFF driver's module name is `cff'.
+   *
+   *   *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine*
+   *
+   *   The rasterizer is positioning horizontal features (e.g., ascender
+   *   height & x-height, or crossbars) on the pixel grid and minimizing the
+   *   amount of antialiasing applied to them, while placing vertical
+   *   features (vertical stems) on the pixel grid without hinting, thus
+   *   representing the stem position and weight accurately.  Sometimes the
+   *   vertical stems may be only partially black.  In this context,
+   *   `antialiasing' means that stems are not positioned exactly on pixel
+   *   borders, causing a fuzzy appearance.
+   *
+   *   There are two principles behind this approach.
+   *
+   *   1) No hinting in the horizontal direction: Unlike `superhinted'
+   *   TrueType, which changes glyph widths to accommodate regular
+   *   inter-glyph spacing, Adobe's approach is `faithful to the design' in
+   *   representing both the glyph width and the inter-glyph spacing
+   *   designed for the font.  This makes the screen display as close as it
+   *   can be to the result one would get with infinite resolution, while
+   *   preserving what is considered the key characteristics of each glyph.
+   *   Note that the distances between unhinted and grid-fitted positions at
+   *   small sizes are comparable to kerning values and thus would be
+   *   noticeable (and distracting) while reading if hinting were applied.
+   *
+   *   One of the reasons to not hint horizontally is antialiasing for LCD
+   *   screens: The pixel geometry of modern displays supplies three
+   *   vertical sub-pixels as the eye moves horizontally across each visible
+   *   pixel.  On devices where we can be certain this characteristic is
+   *   present a rasterizer can take advantage of the sub-pixels to add
+   *   increments of weight.  In Western writing systems this turns out to
+   *   be the more critical direction anyway; the weights and spacing of
+   *   vertical stems (see above) are central to Armenian, Cyrillic, Greek,
+   *   and Latin type designs.  Even when the rasterizer uses greyscale
+   *   antialiasing instead of color (a necessary compromise when one
+   *   doesn't know the screen characteristics), the unhinted vertical
+   *   features preserve the design's weight and spacing much better than
+   *   aliased type would.
+   *
+   *   2) Aligment in the vertical direction: Weights and spacing along the
+   *   y~axis are less critical; what is much more important is the visual
+   *   alignment of related features (like cap-height and x-height).  The
+   *   sense of alignment for these is enhanced by the sharpness of grid-fit
+   *   edges, while the cruder vertical resolution (full pixels instead of
+   *   1/3 pixels) is less of a problem.
+   *
+   *   On the technical side, horizontal alignment zones for ascender,
+   *   x-height, and other important height values (traditionally called
+   *   `blue zones') as defined in the font are positioned independently,
+   *   each being rounded to the nearest pixel edge, taking care of
+   *   overshoot suppression at small sizes, stem darkening, and scaling.
+   *
+   *   Hstems (this is, hint values defined in the font to help align
+   *   horizontal features) that fall within a blue zone are said to be
+   *   `captured' and are aligned to that zone.  Uncaptured stems are moved
+   *   in one of four ways, top edge up or down, bottom edge up or down.
+   *   Unless there are conflicting hstems, the smallest movement is taken
+   *   to minimize distortion.
+   */
+
+
+  /**************************************************************************
+   *
+   * @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_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.  This feature requires
+   *   a rendering system with proper gamma correction.  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_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.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   darkening-parameters
+   *
+   * @description:
+   *   By default, the Adobe CFF engine darkens stems as follows (if the
+   *   `no-stem-darkening' property isn't set):
+   *
+   *   {
+   *     stem width <= 0.5px:   darkening amount = 0.4px
+   *     stem width  = 1px:     darkening amount = 0.275px
+   *     stem width  = 1.667px: darkening amount = 0.275px
+   *     stem width >= 2.333px: darkening amount = 0px
+   *   }
+   *
+   *   and piecewise linear in-between.  Using the `darkening-parameters'
+   *   property, these four control points can be changed, as the following
+   *   example demonstrates.
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Int      darken_params[8] = {  500, 300,   // x1, y1
+   *                                      1000, 200,   // x2, y2
+   *                                      1500, 100,   // x3, y3
+   *                                      2000,   0 }; // x4, y4
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "cff",
+   *                               "darkening-parameters", darken_params );
+   *   }
+   *
+   *   The x~values give the stem width, and the y~values the darkening
+   *   amount.  The unit is 1000th of pixels.  All coordinate values must be
+   *   positive; the x~values must be monotonically increasing; the
+   *   y~values must be monotonically decreasing and smaller than or
+   *   equal to 500 (corresponding to half a pixel); the slope of each
+   *   linear piece must be shallower than -1 (e.g., -.4).
+   *
+   * @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/ftchapters.h
similarity index 97%
rename from include/freetype/ftchapters.h
rename to include/ftchapters.h
index c55670d..d333761 100644
--- a/include/freetype/ftchapters.h
+++ b/include/ftchapters.h
@@ -1,7 +1,7 @@
 /***************************************************************************/
 /*                                                                         */
 /* This file defines the structure of the FreeType reference.              */
-/* It is used by the python script which generates the HTML files.         */
+/* It is used by the python script that generates the HTML files.          */
 /*                                                                         */
 /***************************************************************************/
 
@@ -15,6 +15,7 @@
 /*    General Remarks                                                      */
 /*                                                                         */
 /* <Sections>                                                              */
+/*    header_inclusion                                                     */
 /*    user_allocation                                                      */
 /*                                                                         */
 /***************************************************************************/
diff --git a/include/freetype/ftcid.h b/include/ftcid.h
similarity index 100%
rename from include/freetype/ftcid.h
rename to include/ftcid.h
diff --git a/include/freetype/fterrdef.h b/include/fterrdef.h
similarity index 100%
rename from include/freetype/fterrdef.h
rename to include/fterrdef.h
diff --git a/include/freetype/fterrors.h b/include/fterrors.h
similarity index 100%
rename from include/freetype/fterrors.h
rename to include/fterrors.h
diff --git a/include/freetype/ftgasp.h b/include/ftgasp.h
similarity index 100%
rename from include/freetype/ftgasp.h
rename to include/ftgasp.h
diff --git a/include/freetype/ftglyph.h b/include/ftglyph.h
similarity index 98%
rename from include/freetype/ftglyph.h
rename to include/ftglyph.h
index 31dc331..2d30ed9 100644
--- a/include/freetype/ftglyph.h
+++ b/include/ftglyph.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2008, 2009, 2011 by                         */
+/*  Copyright 1996-2003, 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,       */
@@ -358,17 +358,17 @@
   /*    outline's points, including Bézier control points.  Though it      */
   /*    coincides with the exact bounding box for most glyphs, it can be   */
   /*    slightly larger in some situations (like when rotating an outline  */
-  /*    which contains Bézier outside arcs).                               */
+  /*    that contains Bézier outside arcs).                                */
   /*                                                                       */
   /*    Computing the control box is very fast, while getting the bounding */
   /*    box can take much more time as it needs to walk over all segments  */
   /*    and arcs in the outline.  To get the latter, you can use the       */
-  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*    `ftbbox' component, which is dedicated to this single task.        */
   /*                                                                       */
   /* <Input>                                                               */
   /*    glyph :: A handle to the source glyph object.                      */
   /*                                                                       */
-  /*    mode  :: The mode which indicates how to interpret the returned    */
+  /*    mode  :: The mode that indicates how to interpret the returned     */
   /*             bounding box values.                                      */
   /*                                                                       */
   /* <Output>                                                              */
@@ -388,7 +388,7 @@
   /*    @FT_LOAD_NO_SCALE, the resulting CBox is meaningless.  To get      */
   /*    reasonable values for the CBox it is necessary to load the glyph   */
   /*    at a large ppem value (so that the hinting instructions can        */
-  /*    properly shift and scale the subglyphs), then extracting the CBox  */
+  /*    properly shift and scale the subglyphs), then extracting the CBox, */
   /*    which can be eventually converted back to font units.              */
   /*                                                                       */
   /*    Note that the maximum coordinates are exclusive, which means that  */
diff --git a/include/freetype/ftgxval.h b/include/ftgxval.h
similarity index 97%
rename from include/freetype/ftgxval.h
rename to include/ftgxval.h
index 497015c..6d38e32 100644
--- a/include/freetype/ftgxval.h
+++ b/include/ftgxval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating TrueTypeGX/AAT tables (specification).   */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006 by                                          */
+/*  Copyright 2004-2006, 2013 by                                           */
 /*  Masatake YAMATO, Redhat K.K,                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
@@ -180,7 +180,7 @@
   *
   * @description:
   *    Validate various TrueTypeGX tables to assure that all offsets and
-  *    indices are valid.  The idea is that a higher-level library which
+  *    indices are valid.  The idea is that a higher-level library that
   *    actually does the text layout can access those tables without
   *    error checking (which can be quite time consuming).
   *
@@ -189,7 +189,7 @@
   *       A handle to the input face.
   *
   *    validation_flags ::
-  *       A bit field which specifies the tables to be validated.  See
+  *       A bit field that specifies the tables to be validated.  See
   *       @FT_VALIDATE_GXXXX for possible values.
   *
   *    table_length ::
@@ -286,7 +286,7 @@
   *
   * @description:
   *    Validate classic (16-bit format) kern table to assure that the offsets
-  *    and indices are valid.  The idea is that a higher-level library which
+  *    and indices are valid.  The idea is that a higher-level library that
   *    actually does the text layout can access those tables without error
   *    checking (which can be quite time consuming).
   *
@@ -299,7 +299,7 @@
   *       A handle to the input face.
   *
   *    validation_flags ::
-  *       A bit field which specifies the dialect to be validated.  See
+  *       A bit field that specifies the dialect to be validated.  See
   *       @FT_VALIDATE_CKERNXXX for possible values.
   *
   * @output:
diff --git a/include/freetype/ftgzip.h b/include/ftgzip.h
similarity index 74%
rename from include/freetype/ftgzip.h
rename to include/ftgzip.h
index acbc4f0..78e7269 100644
--- a/include/freetype/ftgzip.h
+++ b/include/ftgzip.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Gzip-compressed stream support.                                      */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2006 by                                    */
+/*  Copyright 2002-2004, 2006, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -91,6 +91,53 @@
   FT_Stream_OpenGzip( FT_Stream  stream,
                       FT_Stream  source );
 
+
+ /************************************************************************
+  *
+  * @function:
+  *   FT_Gzip_Uncompress
+  *
+  * @description:
+  *   Decompress a zipped input buffer into an output buffer.  This function
+  *   is modeled after zlib's `uncompress' function.
+  *
+  * @input:
+  *   memory ::
+  *     A FreeType memory handle.
+  *
+  *   input ::
+  *     The input buffer.
+  *
+  *   input_len ::
+  *     The length of the input buffer.
+  *
+  * @output:
+  *   output::
+  *     The output buffer.
+  *
+  * @inout:
+  *   output_len ::
+  *     Before calling the function, this is the the total size of the
+  *     output buffer, which must be large enough to hold the entire
+  *     uncompressed data (so the size of the uncompressed data must be
+  *     known in advance).  After calling the function, `output_len' is the
+  *     size of the used data in `output'.
+  *
+  * @return:
+  *   FreeType error code.  0~means success.
+  *
+  * @note:
+  *   This function may return `FT_Err_Unimplemented_Feature' if your build
+  *   of FreeType was not compiled with zlib support.
+  */
+  FT_EXPORT( FT_Error )
+  FT_Gzip_Uncompress( FT_Memory       memory,
+                      FT_Byte*        output,
+                      FT_ULong*       output_len,
+                      const FT_Byte*  input,
+                      FT_ULong        input_len );
+
+
  /* */
 
 
diff --git a/include/freetype/ftimage.h b/include/ftimage.h
similarity index 98%
rename from include/freetype/ftimage.h
rename to include/ftimage.h
index 3b826b1..ea71a78 100644
--- a/include/freetype/ftimage.h
+++ b/include/ftimage.h
@@ -555,7 +555,7 @@
   /* <Input>                                                               */
   /*    to   :: A pointer to the target point of the `move to'.            */
   /*                                                                       */
-  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*    user :: A typeless pointer, which is passed from the caller of the */
   /*            decomposition function.                                    */
   /*                                                                       */
   /* <Return>                                                              */
@@ -582,7 +582,7 @@
   /* <Input>                                                               */
   /*    to   :: A pointer to the target point of the `line to'.            */
   /*                                                                       */
-  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*    user :: A typeless pointer, which is passed from the caller of the */
   /*            decomposition function.                                    */
   /*                                                                       */
   /* <Return>                                                              */
@@ -613,7 +613,7 @@
   /*                                                                       */
   /*    to      :: A pointer to the target end point of the conic arc.     */
   /*                                                                       */
-  /*    user    :: A typeless pointer which is passed from the caller of   */
+  /*    user    :: A typeless pointer, which is passed from the caller of  */
   /*               the decomposition function.                             */
   /*                                                                       */
   /* <Return>                                                              */
@@ -645,7 +645,7 @@
   /*                                                                       */
   /*    to       :: A pointer to the target end point.                     */
   /*                                                                       */
-  /*    user     :: A typeless pointer which is passed from the caller of  */
+  /*    user     :: A typeless pointer, which is passed from the caller of */
   /*                the decomposition function.                            */
   /*                                                                       */
   /* <Return>                                                              */
@@ -836,8 +836,8 @@
   /* a a bitmap.  This section contains the public API for rasters.        */
   /*                                                                       */
   /* Note that in FreeType 2, all rasters are now encapsulated within      */
-  /* specific modules called `renderers'.  See `freetype/ftrender.h' for   */
-  /* more details on renderers.                                            */
+  /* specific modules called `renderers'.  See `ftrender.h' for more       */
+  /* details on renderers.                                                 */
   /*                                                                       */
   /*************************************************************************/
 
@@ -891,8 +891,8 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    This structure is used by the span drawing callback type named     */
-  /*    @FT_SpanFunc which takes the y~coordinate of the span as a         */
-  /*    a parameter.                                                       */
+  /*    @FT_SpanFunc that takes the y~coordinate of the span as a          */
+  /*    parameter.                                                         */
   /*                                                                       */
   /*    The coverage value is always between 0 and 255.  If you want less  */
   /*    gray values, the callback function has to reduce them.             */
@@ -1265,7 +1265,7 @@
   /*    XXX: For now, the standard raster doesn't support direct           */
   /*         composition but this should change for the final release (see */
   /*         the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c'    */
-  /*         for examples of distinct implementations which support direct */
+  /*         for examples of distinct implementations that support direct  */
   /*         composition).                                                 */
   /*                                                                       */
   typedef int
diff --git a/include/freetype/ftincrem.h b/include/ftincrem.h
similarity index 100%
rename from include/freetype/ftincrem.h
rename to include/ftincrem.h
diff --git a/include/freetype/ftlcdfil.h b/include/ftlcdfil.h
similarity index 97%
rename from include/freetype/ftlcdfil.h
rename to include/ftlcdfil.h
index 8b253f1..39206f0 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/ftlcdfil.h
@@ -5,7 +5,7 @@
 /*    FreeType API for color filtering of subpixel bitmap glyphs           */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2008, 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,       */
@@ -45,9 +45,9 @@
    *
    * @description:
    *   The @FT_Library_SetLcdFilter API can be used to specify a low-pass
-   *   filter which is then applied to LCD-optimized bitmaps generated
+   *   filter, which is then applied to LCD-optimized bitmaps generated
    *   through @FT_Render_Glyph.  This is useful to reduce color fringes
-   *   which would occur with unfiltered rendering.
+   *   that would occur with unfiltered rendering.
    *
    *   Note that no filter is active by default, and that this function is
    *   *not* implemented in default builds of the library.  You need to
diff --git a/include/freetype/ftlist.h b/include/ftlist.h
similarity index 96%
rename from include/freetype/ftlist.h
rename to include/ftlist.h
index bb6f7f1..241e21e 100644
--- a/include/freetype/ftlist.h
+++ b/include/ftlist.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Generic list support for FreeType (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2007, 2010 by                               */
+/*  Copyright 1996-2001, 2003, 2007, 2010, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -173,7 +173,7 @@
   /*    FT_List_Iterator                                                   */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    An FT_List iterator function which is called during a list parse   */
+  /*    An FT_List iterator function that is called during a list parse    */
   /*    by @FT_List_Iterate.                                               */
   /*                                                                       */
   /* <Input>                                                               */
@@ -200,7 +200,7 @@
   /* <Input>                                                               */
   /*    list     :: A handle to the list.                                  */
   /*    iterator :: An iterator function, called on each node of the list. */
-  /*    user     :: A user-supplied field which is passed as the second    */
+  /*    user     :: A user-supplied field that is passed as the second     */
   /*                argument to the iterator.                              */
   /*                                                                       */
   /* <Return>                                                              */
@@ -218,7 +218,7 @@
   /*    FT_List_Destructor                                                 */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    An @FT_List iterator function which is called during a list        */
+  /*    An @FT_List iterator function that is called during a list         */
   /*    finalization by @FT_List_Finalize to destroy all elements in a     */
   /*    given list.                                                        */
   /*                                                                       */
@@ -250,9 +250,9 @@
   /*    destroy :: A list destructor that will be applied to each element  */
   /*               of the list.                                            */
   /*                                                                       */
-  /*    memory  :: The current memory object which handles deallocation.   */
+  /*    memory  :: The current memory object that handles deallocation.    */
   /*                                                                       */
-  /*    user    :: A user-supplied field which is passed as the last       */
+  /*    user    :: A user-supplied field that is passed as the last        */
   /*               argument to the destructor.                             */
   /*                                                                       */
   /* <Note>                                                                */
diff --git a/include/freetype/ftlzw.h b/include/ftlzw.h
similarity index 100%
rename from include/freetype/ftlzw.h
rename to include/ftlzw.h
diff --git a/include/freetype/ftmac.h b/include/ftmac.h
similarity index 98%
rename from include/freetype/ftmac.h
rename to include/ftmac.h
index ab5bab5..42874fe 100644
--- a/include/freetype/ftmac.h
+++ b/include/ftmac.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Additional Mac-specific API.                                         */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2006, 2007 by                               */
+/*  Copyright 1996-2001, 2004, 2006, 2007, 2013 by                         */
 /*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,7 +18,7 @@
 
 /***************************************************************************/
 /*                                                                         */
-/* NOTE: Include this file after <freetype/freetype.h> and after any       */
+/* NOTE: Include this file after FT_FREETYPE_H and after any               */
 /*       Mac-specific headers (because this header uses Mac types such as  */
 /*       Handle, FSSpec, FSRef, etc.)                                      */
 /*                                                                         */
@@ -168,7 +168,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return a pathname of the disk file and face index for given font   */
-  /*    name which is handled by ATS framework.                            */
+  /*    name that is handled by ATS framework.                             */
   /*                                                                       */
   /* <Input>                                                               */
   /*    fontName    :: Mac OS name of the font in ATS framework.           */
diff --git a/include/freetype/ftmm.h b/include/ftmm.h
similarity index 98%
rename from include/freetype/ftmm.h
rename to include/ftmm.h
index 3aefb9e..837975a 100644
--- a/include/freetype/ftmm.h
+++ b/include/ftmm.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Multiple Master font interface (specification).             */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2006, 2009 by                         */
+/*  Copyright 1996-2001, 2003, 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,       */
@@ -196,7 +196,7 @@
   /*                       number of designs).                             */
   /*                                                                       */
   /*    num_namedstyles :: The number of named styles; only meaningful for */
-  /*                       GX which allows certain design coordinates to   */
+  /*                       GX that allows certain design coordinates to    */
   /*                       have a string ID (in the `name' table)          */
   /*                       associated with them.  The font can tell the    */
   /*                       user that, for example, Weight=1.5 is `Bold'.   */
@@ -258,8 +258,7 @@
   /*                                                                       */
   /* <Output>                                                              */
   /*    amaster :: The Multiple Masters/GX var descriptor.                 */
-  /*               Allocates a data structure, which the user must free    */
-  /*               (a single call to FT_FREE will do it).                  */
+  /*               Allocates a data structure, which the user must free.   */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
diff --git a/include/freetype/ftmodapi.h b/include/ftmodapi.h
similarity index 98%
rename from include/freetype/ftmodapi.h
rename to include/ftmodapi.h
index 8abffb5..22878f8 100644
--- a/include/freetype/ftmodapi.h
+++ b/include/ftmodapi.h
@@ -298,7 +298,7 @@
    *       Note that only a few modules have properties.
    *
    *    value ::
-   *       A generic pointer to a variable or structure which gives the new
+   *       A generic pointer to a variable or structure that 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.
@@ -364,7 +364,7 @@
    *
    * @inout:
    *    value ::
-   *       A generic pointer to a variable or structure which gives the
+   *       A generic pointer to a variable or structure that 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.
@@ -418,7 +418,7 @@
   /*    @FT_Done_Library then only destroys a library if the counter is~1, */
   /*    otherwise it simply decrements the counter.                        */
   /*                                                                       */
-  /*    This function helps in managing life-cycles of structures which    */
+  /*    This function helps in managing life-cycles of structures that     */
   /*    reference @FT_Library objects.                                     */
   /*                                                                       */
   /* <Input>                                                               */
@@ -584,7 +584,7 @@
    *       The library implements a bytecode interpreter that doesn't
    *       support the patented operations of the TrueType virtual machine.
    *
-   *       Its main use is to load certain Asian fonts which position and
+   *       Its main use is to load certain Asian fonts that position and
    *       scale glyph components with bytecode instructions.  It produces
    *       bad output for most other fonts.
    *
diff --git a/include/freetype/ftmoderr.h b/include/ftmoderr.h
similarity index 100%
rename from include/freetype/ftmoderr.h
rename to include/ftmoderr.h
diff --git a/include/freetype/ftotval.h b/include/ftotval.h
similarity index 97%
rename from include/freetype/ftotval.h
rename to include/ftotval.h
index 027f2e8..bb52dc4 100644
--- a/include/freetype/ftotval.h
+++ b/include/ftotval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating OpenType tables (specification).         */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006, 2007 by                                    */
+/*  Copyright 2004-2007, 2013 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -116,7 +116,7 @@
   *
   * @description:
   *    Validate various OpenType tables to assure that all offsets and
-  *    indices are valid.  The idea is that a higher-level library which
+  *    indices are valid.  The idea is that a higher-level library that
   *    actually does the text layout can access those tables without
   *    error checking (which can be quite time consuming).
   *
@@ -125,7 +125,7 @@
   *       A handle to the input face.
   *
   *    validation_flags ::
-  *       A bit field which specifies the tables to be validated.  See
+  *       A bit field that specifies the tables to be validated.  See
   *       @FT_VALIDATE_OTXXX for possible values.
   *
   * @output:
diff --git a/include/freetype/ftoutln.h b/include/ftoutln.h
similarity index 96%
rename from include/freetype/ftoutln.h
rename to include/ftoutln.h
index fd69f28..8c7c57d 100644
--- a/include/freetype/ftoutln.h
+++ b/include/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-2012 by                                      */
+/*  Copyright 1996-2003, 2005-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -97,7 +97,7 @@
   /*                      operations.                                      */
   /*                                                                       */
   /* <InOut>                                                               */
-  /*    user           :: A typeless pointer which is passed to each       */
+  /*    user           :: A typeless pointer that is passed to each        */
   /*                      emitter during the decomposition.  It can be     */
   /*                      used to store the state during the               */
   /*                      decomposition.                                   */
@@ -105,6 +105,13 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    A contour that contains a single point only is represented by a    */
+  /*    `move to' operation followed by `line to' to the same point.  In   */
+  /*    most cases, it is best to filter this out before using the         */
+  /*    outline for stroking purposes (otherwise it would result in a      */
+  /*    visible dot when round caps are used).                             */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Outline_Decompose( FT_Outline*              outline,
                         const FT_Outline_Funcs*  func_interface,
@@ -217,12 +224,12 @@
   /*    the outline's points, including Bézier control points.  Though it  */
   /*    coincides with the exact bounding box for most glyphs, it can be   */
   /*    slightly larger in some situations (like when rotating an outline  */
-  /*    which contains Bézier outside arcs).                               */
+  /*    that contains Bézier outside arcs).                                */
   /*                                                                       */
   /*    Computing the control box is very fast, while getting the bounding */
   /*    box can take much more time as it needs to walk over all segments  */
   /*    and arcs in the outline.  To get the latter, you can use the       */
-  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*    `ftbbox' component, which is dedicated to this single task.        */
   /*                                                                       */
   /* <Input>                                                               */
   /*    outline :: A pointer to the source outline descriptor.             */
@@ -525,9 +532,11 @@
   *
   * @description:
   *   This function analyzes a glyph outline and tries to compute its
-  *   fill orientation (see @FT_Orientation).  This is done by computing
-  *   the direction of each global horizontal and/or vertical extrema
-  *   within the outline.
+  *   fill orientation (see @FT_Orientation).  This is done by integrating 
+  *   the total area covered by the outline. The positive integral
+  *   corresponds to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT
+  *   is returned. The negative integral corresponds to the counter-clockwise
+  *   orientation and @FT_ORIENTATION_TRUETYPE is returned.
   *
   *   Note that this will return @FT_ORIENTATION_TRUETYPE for empty
   *   outlines.
diff --git a/include/freetype/ftpfr.h b/include/ftpfr.h
similarity index 100%
rename from include/freetype/ftpfr.h
rename to include/ftpfr.h
diff --git a/include/freetype/ftrender.h b/include/ftrender.h
similarity index 100%
rename from include/freetype/ftrender.h
rename to include/ftrender.h
diff --git a/include/freetype/ftsizes.h b/include/ftsizes.h
similarity index 98%
rename from include/freetype/ftsizes.h
rename to include/ftsizes.h
index 3e548cc..4167045 100644
--- a/include/freetype/ftsizes.h
+++ b/include/ftsizes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType size objects management (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2006, 2009 by                         */
+/*  Copyright 1996-2001, 2003, 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,       */
@@ -129,7 +129,7 @@
   /* <Description>                                                         */
   /*    Even though it is possible to create several size objects for a    */
   /*    given face (see @FT_New_Size for details), functions like          */
-  /*    @FT_Load_Glyph or @FT_Load_Char only use the one which has been    */
+  /*    @FT_Load_Glyph or @FT_Load_Char only use the one that has been     */
   /*    activated last to determine the `current character pixel size'.    */
   /*                                                                       */
   /*    This function can be used to `activate' a previously created size  */
diff --git a/include/freetype/ftsnames.h b/include/ftsnames.h
similarity index 97%
rename from include/freetype/ftsnames.h
rename to include/ftsnames.h
index 485e4e1..88af440 100644
--- a/include/freetype/ftsnames.h
+++ b/include/ftsnames.h
@@ -7,7 +7,7 @@
 /*                                                                         */
 /*    This is _not_ used to retrieve glyph names!                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2009, 2010 by                   */
+/*  Copyright 1996-2003, 2006, 2009, 2010, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -169,7 +169,7 @@
    *   A constant used as the tag of @FT_Parameter structures to make
    *   FT_Open_Face() ignore preferred family subfamily names in `name'
    *   table since OpenType version 1.4.  For backwards compatibility with
-   *   legacy systems which has 4-face-per-family restriction.
+   *   legacy systems that have a 4-face-per-family restriction.
    *
    */
 #define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY  FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
@@ -184,7 +184,7 @@
    *   A constant used as the tag of @FT_Parameter structures to make
    *   FT_Open_Face() ignore preferred subfamily names in `name' table since
    *   OpenType version 1.4.  For backwards compatibility with legacy
-   *   systems which has 4-face-per-family restriction.
+   *   systems that have a 4-face-per-family restriction.
    *
    */
 #define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY  FT_MAKE_TAG( 'i', 'g', 'p', 's' )
diff --git a/include/freetype/ftstroke.h b/include/ftstroke.h
similarity index 100%
rename from include/freetype/ftstroke.h
rename to include/ftstroke.h
diff --git a/include/freetype/ftsynth.h b/include/ftsynth.h
similarity index 96%
rename from include/freetype/ftsynth.h
rename to include/ftsynth.h
index 2074503..839ab5e 100644
--- a/include/freetype/ftsynth.h
+++ b/include/ftsynth.h
@@ -5,7 +5,7 @@
 /*    FreeType synthesizing code for emboldening and slanting              */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2006, 2008, 2012 by                         */
+/*  Copyright 2000-2001, 2003, 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,       */
@@ -37,7 +37,7 @@
   /* Main reason for not lifting the functions in this module to a  */
   /* `standard' API is that the used parameters for emboldening and */
   /* slanting are not configurable.  Consider the functions as a    */
-  /* code resource which should be copied into the application and  */
+  /* code resource that should be copied into the application and   */
   /* adapted to the particular needs.                               */
 
 
diff --git a/include/freetype/ftsystem.h b/include/ftsystem.h
similarity index 100%
rename from include/freetype/ftsystem.h
rename to include/ftsystem.h
diff --git a/include/freetype/fttrigon.h b/include/fttrigon.h
similarity index 100%
rename from include/freetype/fttrigon.h
rename to include/fttrigon.h
diff --git a/include/freetype/ftttdrv.h b/include/ftttdrv.h
similarity index 85%
rename from include/freetype/ftttdrv.h
rename to include/ftttdrv.h
index d5d3f1c..70ad3d5 100644
--- a/include/freetype/ftttdrv.h
+++ b/include/ftttdrv.h
@@ -61,7 +61,7 @@
    *   interpreter-version
    *
    * @description:
-   *   Currently, two versions are available which represent the bytecode
+   *   Currently, two versions are available, representing 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
@@ -134,6 +134,26 @@
    *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
    *   `FT_Err_Unimplemented_Feature' error.
    *
+   *   Depending on the graphics framework, Microsoft uses different
+   *   bytecode engines.  As a consequence, the version numbers returned by
+   *   a call to the `GETINFO[1]' bytecode instruction are more convoluted
+   *   than desired.
+   *
+   *   {
+   *      framework   Windows version   result of GETINFO[1]
+   *     ----------------------------------------------------
+   *       GDI         before XP         35
+   *       GDI         XP and later      37
+   *       GDI+ old    before Vista      37
+   *       GDI+ old    Vista, 7          38
+   *       GDI+        after 7           40
+   *       DWrite      before 8          39
+   *       DWrite      8 and later       40
+   *   }
+   *
+   *   Since FreeType doesn't provide all capabilities of DWrite ClearType,
+   *   using version~38 seems justified.
+   *
    */
 #define TT_INTERPRETER_VERSION_35  35
 #define TT_INTERPRETER_VERSION_38  38
diff --git a/include/freetype/fttypes.h b/include/fttypes.h
similarity index 98%
rename from include/freetype/fttypes.h
rename to include/fttypes.h
index 027e59c..bd944a4 100644
--- a/include/freetype/fttypes.h
+++ b/include/fttypes.h
@@ -418,7 +418,7 @@
   /*    details of usage.                                                  */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    The address of the FreeType object which is under finalization.    */
+  /*    The address of the FreeType object that is under finalization.     */
   /*    Its client data is accessed through its `generic' field.           */
   /*                                                                       */
   typedef void  (*FT_Generic_Finalizer)(void*  object);
@@ -466,8 +466,8 @@
   /*    FT_MAKE_TAG                                                        */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This macro converts four-letter tags which are used to label       */
-  /*    TrueType tables into an unsigned long to be used within FreeType.  */
+  /*    This macro converts four-letter tags that are used to label        */
+  /*    TrueType tables into an unsigned long, to be used within FreeType. */
   /*                                                                       */
   /* <Note>                                                                */
   /*    The produced values *must* be 32-bit integers.  Don't redefine     */
diff --git a/include/freetype/ftwinfnt.h b/include/ftwinfnt.h
similarity index 97%
rename from include/freetype/ftwinfnt.h
rename to include/ftwinfnt.h
index ea33353..0b67351 100644
--- a/include/freetype/ftwinfnt.h
+++ b/include/ftwinfnt.h
@@ -58,9 +58,10 @@
    * @description:
    *   A list of valid values for the `charset' byte in
    *   @FT_WinFNT_HeaderRec.  Exact mapping tables for the various cpXXXX
-   *   encodings (except for cp1361) can be found at ftp://ftp.unicode.org
-   *   in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory.  cp1361 is
-   *   roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
+   *   encodings (except for cp1361) can be found at
+   *   ftp://ftp.unicode.org/public in the MAPPINGS/VENDORS/MICSFT/WINDOWS
+   *   subdirectory.  cp1361 is roughly a superset of
+   *   MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
    *
    * @values:
    *   FT_WinFNT_ID_DEFAULT ::
diff --git a/include/freetype/ftxf86.h b/include/ftxf86.h
similarity index 96%
rename from include/freetype/ftxf86.h
rename to include/ftxf86.h
index 8c68afd..493cccd 100644
--- a/include/freetype/ftxf86.h
+++ b/include/ftxf86.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Support functions for X11.                                           */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2006, 2007 by                              */
+/*  Copyright 2002-2004, 2006, 2007, 2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -62,7 +62,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*   Return a string describing the format of a given face, using values */
-  /*   which can be used as an X11 FONT_PROPERTY.  Possible values are     */
+  /*   that can be used as an X11 FONT_PROPERTY.  Possible values are      */
   /*   `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */
   /*   `PFR', and `Windows~FNT'.                                           */
   /*                                                                       */
diff --git a/include/freetype/internal/autohint.h b/include/internal/autohint.h
similarity index 100%
rename from include/freetype/internal/autohint.h
rename to include/internal/autohint.h
diff --git a/include/freetype/internal/ftcalc.h b/include/internal/ftcalc.h
similarity index 98%
rename from include/freetype/internal/ftcalc.h
rename to include/internal/ftcalc.h
index faac3a3..03bd68e 100644
--- a/include/freetype/internal/ftcalc.h
+++ b/include/internal/ftcalc.h
@@ -27,10 +27,12 @@
 FT_BEGIN_HEADER
 
 
+#if 0
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_FixedSqrt                                                       */
+  /*    FT_SqrtFixed                                                       */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Computes the square root of a 16.16 fixed-point value.             */
@@ -47,6 +49,8 @@
   FT_BASE( FT_Int32 )
   FT_SqrtFixed( FT_Int32  x );
 
+#endif /* 0 */
+
 
   /*************************************************************************/
   /*                                                                       */
diff --git a/include/freetype/internal/ftdebug.h b/include/internal/ftdebug.h
similarity index 99%
rename from include/freetype/internal/ftdebug.h
rename to include/internal/ftdebug.h
index 1ee120f..58a3916 100644
--- a/include/freetype/internal/ftdebug.h
+++ b/include/internal/ftdebug.h
@@ -247,7 +247,6 @@
   FT_BASE( void )
   ft_debug_init( void );
 
-
 FT_END_HEADER
 
 #endif /* __FTDEBUG_H__ */
diff --git a/include/freetype/internal/ftdriver.h b/include/internal/ftdriver.h
similarity index 100%
rename from include/freetype/internal/ftdriver.h
rename to include/internal/ftdriver.h
diff --git a/include/freetype/internal/ftgloadr.h b/include/internal/ftgloadr.h
similarity index 100%
rename from include/freetype/internal/ftgloadr.h
rename to include/internal/ftgloadr.h
diff --git a/include/freetype/internal/ftmemory.h b/include/internal/ftmemory.h
similarity index 100%
rename from include/freetype/internal/ftmemory.h
rename to include/internal/ftmemory.h
diff --git a/include/freetype/internal/ftobjs.h b/include/internal/ftobjs.h
similarity index 99%
rename from include/freetype/internal/ftobjs.h
rename to include/internal/ftobjs.h
index 8a309b8..701c850 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/internal/ftobjs.h
@@ -363,7 +363,7 @@
 #endif
 
     FT_Bool             ignore_unpatented_hinter;
-    FT_UInt             refcount;
+    FT_Int              refcount;
 
   } FT_Face_InternalRec;
 
@@ -883,7 +883,7 @@
     FT_PIC_Container   pic_container;
 #endif
 
-    FT_UInt            refcount;
+    FT_Int             refcount;
 
   } FT_LibraryRec;
 
diff --git a/include/freetype/internal/ftpic.h b/include/internal/ftpic.h
similarity index 100%
rename from include/freetype/internal/ftpic.h
rename to include/internal/ftpic.h
diff --git a/include/freetype/internal/ftrfork.h b/include/internal/ftrfork.h
similarity index 100%
rename from include/freetype/internal/ftrfork.h
rename to include/internal/ftrfork.h
diff --git a/include/freetype/internal/ftserv.h b/include/internal/ftserv.h
similarity index 95%
rename from include/freetype/internal/ftserv.h
rename to include/internal/ftserv.h
index 4ac988b..1203ec8 100644
--- a/include/freetype/internal/ftserv.h
+++ b/include/internal/ftserv.h
@@ -34,14 +34,6 @@
 
 FT_BEGIN_HEADER
 
-#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 */
-
   /*
    * @macro:
    *   FT_FACE_FIND_SERVICE
@@ -742,31 +734,27 @@
    *  The header files containing the services.
    */
 
-#define FT_SERVICE_BDF_H                <freetype/internal/services/svbdf.h>
-#define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
-#define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
-#define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
-#define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
-#define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
-#define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
-#define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
-#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>
-#define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>
-#define FT_SERVICE_XFREE86_NAME_H       <freetype/internal/services/svxf86nm.h>
-#define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
+#define FT_SERVICE_BDF_H                <internal/services/svbdf.h>
+#define FT_SERVICE_CID_H                <internal/services/svcid.h>
+#define FT_SERVICE_GLYPH_DICT_H         <internal/services/svgldict.h>
+#define FT_SERVICE_GX_VALIDATE_H        <internal/services/svgxval.h>
+#define FT_SERVICE_KERNING_H            <internal/services/svkern.h>
+#define FT_SERVICE_MULTIPLE_MASTERS_H   <internal/services/svmm.h>
+#define FT_SERVICE_OPENTYPE_VALIDATE_H  <internal/services/svotval.h>
+#define FT_SERVICE_PFR_H                <internal/services/svpfr.h>
+#define FT_SERVICE_POSTSCRIPT_CMAPS_H   <internal/services/svpscmap.h>
+#define FT_SERVICE_POSTSCRIPT_INFO_H    <internal/services/svpsinfo.h>
+#define FT_SERVICE_POSTSCRIPT_NAME_H    <internal/services/svpostnm.h>
+#define FT_SERVICE_PROPERTIES_H         <internal/services/svprop.h>
+#define FT_SERVICE_SFNT_H               <internal/services/svsfnt.h>
+#define FT_SERVICE_TRUETYPE_ENGINE_H    <internal/services/svtteng.h>
+#define FT_SERVICE_TT_CMAP_H            <internal/services/svttcmap.h>
+#define FT_SERVICE_WINFNT_H             <internal/services/svwinfnt.h>
+#define FT_SERVICE_XFREE86_NAME_H       <internal/services/svxf86nm.h>
+#define FT_SERVICE_TRUETYPE_GLYF_H      <internal/services/svttglyf.h>
 
  /* */
 
-#if defined( _MSC_VER )
-#pragma warning( pop )
-#endif
-
 FT_END_HEADER
 
 #endif /* __FTSERV_H__ */
diff --git a/include/freetype/internal/ftstream.h b/include/internal/ftstream.h
similarity index 100%
rename from include/freetype/internal/ftstream.h
rename to include/internal/ftstream.h
diff --git a/include/freetype/internal/fttrace.h b/include/internal/fttrace.h
similarity index 100%
rename from include/freetype/internal/fttrace.h
rename to include/internal/fttrace.h
diff --git a/include/freetype/internal/ftvalid.h b/include/internal/ftvalid.h
similarity index 100%
rename from include/freetype/internal/ftvalid.h
rename to include/internal/ftvalid.h
diff --git a/include/internal/internal.h b/include/internal/internal.h
new file mode 100644
index 0000000..e0ddb06
--- /dev/null
+++ b/include/internal/internal.h
@@ -0,0 +1,63 @@
+/***************************************************************************/
+/*                                                                         */
+/*  internal.h                                                             */
+/*                                                                         */
+/*    Internal header files (specification only).                          */
+/*                                                                         */
+/*  Copyright 1996-2004, 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is automatically included by `ft2build.h'.                  */
+  /* Do not include it manually!                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FT_INTERNAL_OBJECTS_H             <internal/ftobjs.h>
+#define FT_INTERNAL_PIC_H                 <internal/ftpic.h>
+#define FT_INTERNAL_STREAM_H              <internal/ftstream.h>
+#define FT_INTERNAL_MEMORY_H              <internal/ftmemory.h>
+#define FT_INTERNAL_DEBUG_H               <internal/ftdebug.h>
+#define FT_INTERNAL_CALC_H                <internal/ftcalc.h>
+#define FT_INTERNAL_DRIVER_H              <internal/ftdriver.h>
+#define FT_INTERNAL_TRACE_H               <internal/fttrace.h>
+#define FT_INTERNAL_GLYPH_LOADER_H        <internal/ftgloadr.h>
+#define FT_INTERNAL_SFNT_H                <internal/sfnt.h>
+#define FT_INTERNAL_SERVICE_H             <internal/ftserv.h>
+#define FT_INTERNAL_RFORK_H               <internal/ftrfork.h>
+#define FT_INTERNAL_VALIDATE_H            <internal/ftvalid.h>
+
+#define FT_INTERNAL_TRUETYPE_TYPES_H      <internal/tttypes.h>
+#define FT_INTERNAL_TYPE1_TYPES_H         <internal/t1types.h>
+
+#define FT_INTERNAL_POSTSCRIPT_AUX_H      <internal/psaux.h>
+#define FT_INTERNAL_POSTSCRIPT_HINTS_H    <internal/pshints.h>
+#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H  <internal/psglobal.h>
+
+#define FT_INTERNAL_AUTOHINT_H            <internal/autohint.h>
+
+
+#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.  */
+  /* In particular, the warning complains about stuff like `while(0)' */
+  /* which is very useful in macro definitions.  There is no benefit  */
+  /* in having it enabled.                                            */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+
+
+/* END */
diff --git a/include/freetype/internal/psaux.h b/include/internal/psaux.h
similarity index 100%
rename from include/freetype/internal/psaux.h
rename to include/internal/psaux.h
diff --git a/include/freetype/internal/pshints.h b/include/internal/pshints.h
similarity index 100%
rename from include/freetype/internal/pshints.h
rename to include/internal/pshints.h
diff --git a/include/freetype/internal/services/svbdf.h b/include/internal/services/svbdf.h
similarity index 100%
rename from include/freetype/internal/services/svbdf.h
rename to include/internal/services/svbdf.h
diff --git a/include/freetype/internal/services/svcid.h b/include/internal/services/svcid.h
similarity index 100%
rename from include/freetype/internal/services/svcid.h
rename to include/internal/services/svcid.h
diff --git a/include/freetype/internal/services/svgldict.h b/include/internal/services/svgldict.h
similarity index 100%
rename from include/freetype/internal/services/svgldict.h
rename to include/internal/services/svgldict.h
diff --git a/include/freetype/internal/services/svgxval.h b/include/internal/services/svgxval.h
similarity index 100%
rename from include/freetype/internal/services/svgxval.h
rename to include/internal/services/svgxval.h
diff --git a/include/freetype/internal/services/svkern.h b/include/internal/services/svkern.h
similarity index 100%
rename from include/freetype/internal/services/svkern.h
rename to include/internal/services/svkern.h
diff --git a/include/freetype/internal/services/svmm.h b/include/internal/services/svmm.h
similarity index 100%
rename from include/freetype/internal/services/svmm.h
rename to include/internal/services/svmm.h
diff --git a/include/freetype/internal/services/svotval.h b/include/internal/services/svotval.h
similarity index 100%
rename from include/freetype/internal/services/svotval.h
rename to include/internal/services/svotval.h
diff --git a/include/freetype/internal/services/svpfr.h b/include/internal/services/svpfr.h
similarity index 100%
rename from include/freetype/internal/services/svpfr.h
rename to include/internal/services/svpfr.h
diff --git a/include/freetype/internal/services/svpostnm.h b/include/internal/services/svpostnm.h
similarity index 100%
rename from include/freetype/internal/services/svpostnm.h
rename to include/internal/services/svpostnm.h
diff --git a/include/freetype/internal/services/svprop.h b/include/internal/services/svprop.h
similarity index 100%
rename from include/freetype/internal/services/svprop.h
rename to include/internal/services/svprop.h
diff --git a/include/freetype/internal/services/svpscmap.h b/include/internal/services/svpscmap.h
similarity index 100%
rename from include/freetype/internal/services/svpscmap.h
rename to include/internal/services/svpscmap.h
diff --git a/include/freetype/internal/services/svpsinfo.h b/include/internal/services/svpsinfo.h
similarity index 100%
rename from include/freetype/internal/services/svpsinfo.h
rename to include/internal/services/svpsinfo.h
diff --git a/include/freetype/internal/services/svsfnt.h b/include/internal/services/svsfnt.h
similarity index 100%
rename from include/freetype/internal/services/svsfnt.h
rename to include/internal/services/svsfnt.h
diff --git a/include/freetype/internal/services/svttcmap.h b/include/internal/services/svttcmap.h
similarity index 97%
rename from include/freetype/internal/services/svttcmap.h
rename to include/internal/services/svttcmap.h
index 83994aa..4370f4c 100644
--- a/include/freetype/internal/services/svttcmap.h
+++ b/include/internal/services/svttcmap.h
@@ -7,7 +7,7 @@
 /*  Copyright 2003 by                                                      */
 /*  Masatake YAMATO, Redhat K.K.                                           */
 /*                                                                         */
-/*  Copyright 2003, 2008, 2009, 2012 by                                    */
+/*  Copyright 2003, 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,       */
@@ -47,7 +47,7 @@
   /* <Fields>                                                              */
   /*    language ::                                                        */
   /*      The language ID used in Mac fonts.  Definitions of values are in */
-  /*      freetype/ttnameid.h.                                             */
+  /*      `ttnameid.h'.                                                    */
   /*                                                                       */
   /*    format ::                                                          */
   /*      The cmap format.  OpenType 1.5 defines the formats 0 (byte       */
diff --git a/include/freetype/internal/services/svtteng.h b/include/internal/services/svtteng.h
similarity index 100%
rename from include/freetype/internal/services/svtteng.h
rename to include/internal/services/svtteng.h
diff --git a/include/freetype/internal/services/svttglyf.h b/include/internal/services/svttglyf.h
similarity index 100%
rename from include/freetype/internal/services/svttglyf.h
rename to include/internal/services/svttglyf.h
diff --git a/include/freetype/internal/services/svwinfnt.h b/include/internal/services/svwinfnt.h
similarity index 100%
rename from include/freetype/internal/services/svwinfnt.h
rename to include/internal/services/svwinfnt.h
diff --git a/include/freetype/internal/services/svxf86nm.h b/include/internal/services/svxf86nm.h
similarity index 100%
rename from include/freetype/internal/services/svxf86nm.h
rename to include/internal/services/svxf86nm.h
diff --git a/include/freetype/internal/sfnt.h b/include/internal/sfnt.h
similarity index 100%
rename from include/freetype/internal/sfnt.h
rename to include/internal/sfnt.h
diff --git a/include/freetype/internal/t1types.h b/include/internal/t1types.h
similarity index 100%
rename from include/freetype/internal/t1types.h
rename to include/internal/t1types.h
diff --git a/include/freetype/internal/tttypes.h b/include/internal/tttypes.h
similarity index 94%
rename from include/freetype/internal/tttypes.h
rename to include/internal/tttypes.h
index 1bbfe49..ad302b8 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/internal/tttypes.h
@@ -140,6 +140,75 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
+  /*    WOFF_HeaderRec                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    WOFF file format header.                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    See                                                                */
+  /*                                                                       */
+  /*      http://www.w3.org/TR/WOFF/#WOFFHeader                            */
+  /*                                                                       */
+  typedef struct  WOFF_HeaderRec_
+  {
+    FT_ULong   signature;
+    FT_ULong   flavor;
+    FT_ULong   length;
+    FT_UShort  num_tables;
+    FT_UShort  reserved;
+    FT_ULong   totalSfntSize;
+    FT_UShort  majorVersion;
+    FT_UShort  minorVersion;
+    FT_ULong   metaOffset;
+    FT_ULong   metaLength;
+    FT_ULong   metaOrigLength;
+    FT_ULong   privOffset;
+    FT_ULong   privLength;
+
+  } WOFF_HeaderRec, *WOFF_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    WOFF_TableRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes a given table of a WOFF font.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Tag        :: A four-bytes tag describing the table.               */
+  /*                                                                       */
+  /*    Offset     :: The offset of the table from the start of the WOFF   */
+  /*                  font in its resource.                                */
+  /*                                                                       */
+  /*    CompLength :: Compressed table length (in bytes).                  */
+  /*                                                                       */
+  /*    OrigLength :: Unompressed table length (in bytes).                 */
+  /*                                                                       */
+  /*    CheckSum   :: The table checksum.  This value can be ignored.      */
+  /*                                                                       */
+  /*    OrigOffset :: The uncompressed table file offset.  This value gets */
+  /*                  computed while constructing the (uncompressed) SFNT  */
+  /*                  header.  It is not contained in the WOFF file.       */
+  /*                                                                       */
+  typedef struct  WOFF_TableRec_
+  {
+    FT_ULong  Tag;           /* table ID                  */
+    FT_ULong  Offset;        /* table file offset         */
+    FT_ULong  CompLength;    /* compressed table length   */
+    FT_ULong  OrigLength;    /* uncompressed table length */
+    FT_ULong  CheckSum;      /* uncompressed checksum     */
+
+    FT_ULong  OrigOffset;    /* uncompressed table file offset */
+                             /* (not in the WOFF file)         */
+  } WOFF_TableRec, *WOFF_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
   /*    TT_LongMetricsRec                                                  */
   /*                                                                       */
   /* <Description>                                                         */
@@ -353,16 +422,16 @@
   /*                                                                       */
   typedef struct  TT_SBit_MetricsRec_
   {
-    FT_Byte  height;
-    FT_Byte  width;
+    FT_UShort  height;
+    FT_UShort  width;
 
-    FT_Char  horiBearingX;
-    FT_Char  horiBearingY;
-    FT_Byte  horiAdvance;
+    FT_Short   horiBearingX;
+    FT_Short   horiBearingY;
+    FT_UShort  horiAdvance;
 
-    FT_Char  vertBearingX;
-    FT_Char  vertBearingY;
-    FT_Byte  vertAdvance;
+    FT_Short   vertBearingX;
+    FT_Short   vertBearingY;
+    FT_UShort  vertAdvance;
 
   } TT_SBit_MetricsRec, *TT_SBit_Metrics;
 
@@ -979,6 +1048,20 @@
   (*TT_Loader_EndGlyphFunc)( TT_Loader  loader );
 
 
+  typedef enum TT_SbitTableType_
+  {
+    TT_SBIT_TABLE_TYPE_NONE = 0,
+    TT_SBIT_TABLE_TYPE_EBLC, /* `EBLC' (Microsoft), */
+                             /* `bloc' (Apple)      */
+    TT_SBIT_TABLE_TYPE_CBLC, /* `CBLC' (Google)     */
+    TT_SBIT_TABLE_TYPE_SBIX, /* `sbix' (Apple)      */
+
+    /* do not remove */
+    TT_SBIT_TABLE_TYPE_MAX
+
+  } TT_SbitTableType;
+
+
   /*************************************************************************/
   /*                                                                       */
   /*                         TrueType Face Type                            */
@@ -1090,13 +1173,6 @@
   /*                                                                       */
   /*    pclt                 :: The `pclt' SFNT table.                     */
   /*                                                                       */
-  /*    num_sbit_strikes     :: The number of sbit strikes, i.e., bitmap   */
-  /*                            sizes, embedded in this font.              */
-  /*                                                                       */
-  /*    sbit_strikes         :: An array of sbit strikes embedded in this  */
-  /*                            font.  This table is optional in a         */
-  /*                            TrueType/OpenType font.                    */
-  /*                                                                       */
   /*    num_sbit_scales      :: The number of sbit scales for this font.   */
   /*                                                                       */
   /*    sbit_scales          :: Array of sbit scales embedded in this      */
@@ -1302,6 +1378,7 @@
 
     FT_Byte*              sbit_table;
     FT_ULong              sbit_table_size;
+    TT_SbitTableType      sbit_table_type;
     FT_UInt               sbit_num_strikes;
 
     FT_Byte*              kern_table;
@@ -1402,7 +1479,6 @@
     FT_Int           advance;
     FT_Int           linear;
     FT_Bool          linear_def;
-    FT_Bool          preserve_pps;
     FT_Vector        pp1;
     FT_Vector        pp2;
 
diff --git a/include/freetype/t1tables.h b/include/t1tables.h
similarity index 100%
rename from include/freetype/t1tables.h
rename to include/t1tables.h
diff --git a/include/freetype/ttnameid.h b/include/ttnameid.h
similarity index 99%
rename from include/freetype/ttnameid.h
rename to include/ttnameid.h
index 173f88c..9711d1d 100644
--- a/include/freetype/ttnameid.h
+++ b/include/ttnameid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType name ID definitions (specification only).                   */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2008, 2012 by                                */
+/*  Copyright 1996-2004, 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,       */
@@ -1208,7 +1208,7 @@
   /*                                                                       */
   /* Here some alias #defines in order to be clearer.                      */
   /*                                                                       */
-  /* These are not always #defined to stay within the 31~character limit   */
+  /* These are not always #defined to stay within the 31~character limit,  */
   /* which some compilers have.                                            */
   /*                                                                       */
   /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern  */
diff --git a/include/freetype/tttables.h b/include/tttables.h
similarity index 96%
rename from include/freetype/tttables.h
rename to include/tttables.h
index fe07117..bb49dc0 100644
--- a/include/freetype/tttables.h
+++ b/include/tttables.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType tables definitions and interface                 */
 /*    (specification only).                                                */
 /*                                                                         */
-/*  Copyright 1996-2005, 2008-2012 by                                      */
+/*  Copyright 1996-2005, 2008-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -170,8 +170,8 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
-  /*               be identical except for the names of their fields which */
-  /*               are different.                                          */
+  /*               be identical except for the names of their fields,      */
+  /*               which are different.                                    */
   /*                                                                       */
   /*               This ensures that a single function in the `ttload'     */
   /*               module is able to read both the horizontal and vertical */
@@ -296,8 +296,8 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
-  /*               be identical except for the names of their fields which */
-  /*               are different.                                          */
+  /*               be identical except for the names of their fields,      */
+  /*               which are different.                                    */
   /*                                                                       */
   /*               This ensures that a single function in the `ttload'     */
   /*               module is able to read both the horizontal and vertical */
@@ -340,12 +340,11 @@
   /*    TT_OS2                                                             */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A structure used to model a TrueType OS/2 table. This is the long  */
-  /*    table version.  All fields comply to the TrueType specification.   */
+  /*    A structure used to model a TrueType OS/2 table.  All fields       */
+  /*    comply to the OpenType specification.                              */
   /*                                                                       */
-  /*    Note that we now support old Mac fonts which do not include an     */
-  /*    OS/2 table.  In this case, the `version' field is always set to    */
-  /*    0xFFFF.                                                            */
+  /*    Note that we now support old Mac fonts that do not include an OS/2 */
+  /*    table.  In this case, the `version' field is always set to 0xFFFF. */
   /*                                                                       */
   typedef struct  TT_OS2_
   {
@@ -384,12 +383,12 @@
     FT_UShort  usWinAscent;
     FT_UShort  usWinDescent;
 
-    /* only version 1 tables: */
+    /* only version 1 and higher: */
 
     FT_ULong   ulCodePageRange1;       /* Bits 0-31   */
     FT_ULong   ulCodePageRange2;       /* Bits 32-63  */
 
-    /* only version 2 tables: */
+    /* only version 2 and higher: */
 
     FT_Short   sxHeight;
     FT_Short   sCapHeight;
@@ -397,6 +396,11 @@
     FT_UShort  usBreakChar;
     FT_UShort  usMaxContext;
 
+    /* only version 5 and higher: */
+
+    FT_UShort  usLowerOpticalPointSize;       /* in twips (1/20th points) */
+    FT_UShort  usUpperOpticalPointSize;       /* in twips (1/20th points) */
+
   } TT_OS2;
 
 
@@ -465,7 +469,7 @@
   /*    TT_MaxProfile                                                      */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    The maximum profile is a table containing many max values which    */
+  /*    The maximum profile is a table containing many max values, which   */
   /*    can be used to pre-allocate arrays.  This ensures that no memory   */
   /*    allocation occurs during a glyph load.                             */
   /*                                                                       */
@@ -672,6 +676,12 @@
   *       error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
   *       if ( error ) { ... could not load table ... }
   *     }
+  *
+  *   Note that structures like @TT_Header or @TT_OS2 can't be used with
+  *   this function; they are limited to @FT_Get_Sfnt_Table.  Reason is that
+  *   those structures depend on the processor architecture, with varying
+  *   size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian).
+  *
   */
   FT_EXPORT( FT_Error )
   FT_Load_Sfnt_Table( FT_Face    face,
@@ -730,7 +740,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return TrueType/sfnt specific cmap language ID.  Definitions of    */
-  /*    language ID values are in `freetype/ttnameid.h'.                   */
+  /*    language ID values are in `ttnameid.h'.                            */
   /*                                                                       */
   /* <Input>                                                               */
   /*    charmap ::                                                         */
diff --git a/include/freetype/tttags.h b/include/tttags.h
similarity index 97%
rename from include/freetype/tttags.h
rename to include/tttags.h
index be8c524..d59aa19 100644
--- a/include/freetype/tttags.h
+++ b/include/tttags.h
@@ -88,6 +88,7 @@
 #define TTAG_post  FT_MAKE_TAG( 'p', 'o', 's', 't' )
 #define TTAG_prep  FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
 #define TTAG_prop  FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
+#define TTAG_sbix  FT_MAKE_TAG( 's', 'b', 'i', 'x' )
 #define TTAG_sfnt  FT_MAKE_TAG( 's', 'f', 'n', 't' )
 #define TTAG_SING  FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
 #define TTAG_trak  FT_MAKE_TAG( 't', 'r', 'a', 'k' )
@@ -99,6 +100,7 @@
 #define TTAG_VDMX  FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
 #define TTAG_vhea  FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
 #define TTAG_vmtx  FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+#define TTAG_wOFF  FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
 
 
 FT_END_HEADER
diff --git a/include/freetype/ttunpat.h b/include/ttunpat.h
similarity index 100%
rename from include/freetype/ttunpat.h
rename to include/ttunpat.h
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
new file mode 100644
index 0000000..22ef6d5
--- /dev/null
+++ b/src/autofit/afblue.c
@@ -0,0 +1,166 @@
+/* This file has been generated by the Perl script `afblue.pl', */
+/* using data from file `afblue.dat'.                           */
+
+/***************************************************************************/
+/*                                                                         */
+/*  afblue.c                                                               */
+/*                                                                         */
+/*    Auto-fitter data for blue strings (body).                            */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "aftypes.h"
+
+
+  FT_LOCAL_ARRAY_DEF( char )
+  af_blue_strings[] =
+  {
+    /* */
+    'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S',  /* THEZOCQS */
+    '\0',
+    'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S',  /* HEZLOCUS */
+    '\0',
+    'f', 'i', 'j', 'k', 'd', 'b', 'h',  /* fijkdbh */
+    '\0',
+    'x', 'z', 'r', 'o', 'e', 's', 'c',  /* xzroesc */
+    '\0',
+    'p', 'q', 'g', 'j', 'y',  /* pqgjy */
+    '\0',
+    '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9',  /* ΓΒΕΖΘΟΩ */
+    '\0',
+    '\xCE', '\x92', '\xCE', '\x94', '\xCE', '\x96', '\xCE', '\x9E', '\xCE', '\x98', '\xCE', '\x9F',  /* ΒΔΖΞΘΟ */
+    '\0',
+    '\xCE', '\xB2', '\xCE', '\xB8', '\xCE', '\xB4', '\xCE', '\xB6', '\xCE', '\xBB', '\xCE', '\xBE',  /* βθδζλξ */
+    '\0',
+    '\xCE', '\xB1', '\xCE', '\xB5', '\xCE', '\xB9', '\xCE', '\xBF', '\xCF', '\x80', '\xCF', '\x83', '\xCF', '\x84', '\xCF', '\x89',  /* αειοπστω */
+    '\0',
+    '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88',  /* βγημρφχψ */
+    '\0',
+    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕПЗОСЭ */
+    '\0',
+    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕШЗОСЭ */
+    '\0',
+    '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81',  /* хпншезос */
+    '\0',
+    '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84',  /* руф */
+    '\0',
+    '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1',  /* בדהחךכםס */
+    '\0',
+    '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6',  /* בטכםסצ */
+    '\0',
+    '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5',  /* קךןףץ */
+#ifdef AF_CONFIG_OPTION_CJK
+    '\0',
+    '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0',  /* 他们你來們到和地 */
+    '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', '\xE5', '\xB8', '\xAD', '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x83',  /* 对對就席我时時會 */
+    '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\x83', '\xBD', '\xE8', '\x88', '\xB0', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99',  /* 来為能舰說说这這 */
+    '\xE9', '\xBD', '\x8A',  /* 齊 */
+    '\0',
+    '\xE5', '\x86', '\x9B', '\xE5', '\x90', '\x8C', '\xE5', '\xB7', '\xB2', '\xE6', '\x84', '\xBF', '\xE6', '\x97', '\xA2', '\xE6', '\x98', '\x9F', '\xE6', '\x98', '\xAF', '\xE6', '\x99', '\xAF',  /* 军同已愿既星是景 */
+    '\xE6', '\xB0', '\x91', '\xE7', '\x85', '\xA7', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\xA8', '\xE7', '\xBD', '\xAE', '\xE8', '\xA6', '\x81',  /* 民照现現理用置要 */
+    '\xE8', '\xBB', '\x8D', '\xE9', '\x82', '\xA3', '\xE9', '\x85', '\x8D', '\xE9', '\x87', '\x8C', '\xE9', '\x96', '\x8B', '\xE9', '\x9B', '\xB7', '\xE9', '\x9C', '\xB2', '\xE9', '\x9D', '\xA2',  /* 軍那配里開雷露面 */
+    '\xE9', '\xA1', '\xBE',  /* 顾 */
+    '\0',
+    '\xE4', '\xB8', '\xAA', '\xE4', '\xB8', '\xBA', '\xE4', '\xBA', '\xBA', '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xA5', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86',  /* 个为人他以们你來 */
+    '\xE5', '\x80', '\x8B', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\xA4', '\xA7', '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1',  /* 個們到和大对對就 */
+    '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x89', '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\xA6', '\x81', '\xE8', '\xAA', '\xAA',  /* 我时時有来為要說 */
+    '\xE8', '\xAF', '\xB4',  /* 说 */
+    '\0',
+    '\xE4', '\xB8', '\xBB', '\xE4', '\xBA', '\x9B', '\xE5', '\x9B', '\xA0', '\xE5', '\xAE', '\x83', '\xE6', '\x83', '\xB3', '\xE6', '\x84', '\x8F', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\x9F',  /* 主些因它想意理生 */
+    '\xE7', '\x95', '\xB6', '\xE7', '\x9C', '\x8B', '\xE7', '\x9D', '\x80', '\xE7', '\xBD', '\xAE', '\xE8', '\x80', '\x85', '\xE8', '\x87', '\xAA', '\xE8', '\x91', '\x97', '\xE8', '\xA3', '\xA1',  /* 當看着置者自著裡 */
+    '\xE8', '\xBF', '\x87', '\xE8', '\xBF', '\x98', '\xE8', '\xBF', '\x9B', '\xE9', '\x80', '\xB2', '\xE9', '\x81', '\x8E', '\xE9', '\x81', '\x93', '\xE9', '\x82', '\x84', '\xE9', '\x87', '\x8C',  /* 过还进進過道還里 */
+    '\xE9', '\x9D', '\xA2',  /* 面 */
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    '\0',
+    '\xE4', '\xBA', '\x9B', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0',  /* 些们你來們到和地 */
+    '\xE5', '\xA5', '\xB9', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE5', '\xB0', '\xB1', '\xE5', '\xB9', '\xB4', '\xE5', '\xBE', '\x97', '\xE6', '\x83', '\x85', '\xE6', '\x9C', '\x80',  /* 她将將就年得情最 */
+    '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE7', '\x90', '\x86', '\xE8', '\x83', '\xBD', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99',  /* 样樣理能說说这這 */
+    '\xE9', '\x80', '\x9A',  /* 通 */
+    '\0',
+    '\xE5', '\x8D', '\xB3', '\xE5', '\x90', '\x97', '\xE5', '\x90', '\xA7', '\xE5', '\x90', '\xAC', '\xE5', '\x91', '\xA2', '\xE5', '\x93', '\x81', '\xE5', '\x93', '\x8D', '\xE5', '\x97', '\x8E',  /* 即吗吧听呢品响嗎 */
+    '\xE5', '\xB8', '\x88', '\xE5', '\xB8', '\xAB', '\xE6', '\x94', '\xB6', '\xE6', '\x96', '\xAD', '\xE6', '\x96', '\xB7', '\xE6', '\x98', '\x8E', '\xE7', '\x9C', '\xBC', '\xE9', '\x96', '\x93',  /* 师師收断斷明眼間 */
+    '\xE9', '\x97', '\xB4', '\xE9', '\x99', '\x85', '\xE9', '\x99', '\x88', '\xE9', '\x99', '\x90', '\xE9', '\x99', '\xA4', '\xE9', '\x99', '\xB3', '\xE9', '\x9A', '\x8F', '\xE9', '\x9A', '\x9B',  /* 间际陈限除陳随際 */
+    '\xE9', '\x9A', '\xA8',  /* 隨 */
+    '\0',
+    '\xE4', '\xBA', '\x8B', '\xE5', '\x89', '\x8D', '\xE5', '\xAD', '\xB8', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE6', '\x83', '\x85', '\xE6', '\x83', '\xB3', '\xE6', '\x88', '\x96',  /* 事前學将將情想或 */
+    '\xE6', '\x94', '\xBF', '\xE6', '\x96', '\xAF', '\xE6', '\x96', '\xB0', '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE6', '\xB0', '\x91', '\xE6', '\xB2', '\x92', '\xE6', '\xB2', '\xA1',  /* 政斯新样樣民沒没 */
+    '\xE7', '\x84', '\xB6', '\xE7', '\x89', '\xB9', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x83', '\xE7', '\xAC', '\xAC', '\xE7', '\xB6', '\x93', '\xE8', '\xB0', '\x81',  /* 然特现現球第經谁 */
+    '\xE8', '\xB5', '\xB7',  /* 起 */
+    '\0',
+    '\xE4', '\xBE', '\x8B', '\xE5', '\x88', '\xA5', '\xE5', '\x88', '\xAB', '\xE5', '\x88', '\xB6', '\xE5', '\x8A', '\xA8', '\xE5', '\x8B', '\x95', '\xE5', '\x90', '\x97', '\xE5', '\x97', '\x8E',  /* 例別别制动動吗嗎 */
+    '\xE5', '\xA2', '\x9E', '\xE6', '\x8C', '\x87', '\xE6', '\x98', '\x8E', '\xE6', '\x9C', '\x9D', '\xE6', '\x9C', '\x9F', '\xE6', '\x9E', '\x84', '\xE7', '\x89', '\xA9', '\xE7', '\xA1', '\xAE',  /* 增指明朝期构物确 */
+    '\xE7', '\xA7', '\x8D', '\xE8', '\xAA', '\xBF', '\xE8', '\xB0', '\x83', '\xE8', '\xB2', '\xBB', '\xE8', '\xB4', '\xB9', '\xE9', '\x82', '\xA3', '\xE9', '\x83', '\xBD', '\xE9', '\x96', '\x93',  /* 种調调費费那都間 */
+    '\xE9', '\x97', '\xB4',  /* 间 */
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+#endif /* AF_CONFIG_OPTION_CJK                */
+    '\0',
+
+  };
+
+
+  /* stringsets are specific to scripts */
+  FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
+  af_blue_stringsets[] =
+  {
+    /* */
+    { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_LATIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_LATIN_SMALL,           0                                 },
+    { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GREEK_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GREEK_SMALL,           0                                 },
+    { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           0                                 },
+    { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                      0                                 },
+    { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
+                                       AF_BLUE_PROPERTY_LATIN_LONG   },
+    { AF_BLUE_STRING_HEBREW_BOTTOM,    0                             },
+    { AF_BLUE_STRING_HEBREW_DESCENDER, 0                             },
+    { AF_BLUE_STRING_MAX,              0                             },
+#ifdef AF_CONFIG_OPTION_CJK
+    { AF_BLUE_STRING_CJK_TOP_FILL,      AF_BLUE_PROPERTY_CJK_TOP |
+                                        AF_BLUE_PROPERTY_CJK_FILL    },
+    { AF_BLUE_STRING_CJK_TOP_UNFILL,    AF_BLUE_PROPERTY_CJK_TOP     },
+    { AF_BLUE_STRING_CJK_BOTTOM_FILL,   AF_BLUE_PROPERTY_CJK_FILL    },
+    { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0                            },
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    { AF_BLUE_STRING_CJK_LEFT_FILL,     AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_FILL    },
+    { AF_BLUE_STRING_CJK_LEFT_UNFILL,   AF_BLUE_PROPERTY_CJK_HORIZ   },
+    { AF_BLUE_STRING_CJK_RIGHT_FILL,    AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_RIGHT |
+                                        AF_BLUE_PROPERTY_CJK_FILL    },
+    { AF_BLUE_STRING_CJK_RIGHT_UNFILL,  AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_RIGHT   },
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+    { AF_BLUE_STRING_MAX,               0                            },
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+  };
+
+
+/* END */
diff --git a/src/autofit/afblue.cin b/src/autofit/afblue.cin
new file mode 100644
index 0000000..c693d89
--- /dev/null
+++ b/src/autofit/afblue.cin
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afblue.c                                                               */
+/*                                                                         */
+/*    Auto-fitter data for blue strings (body).                            */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "aftypes.h"
+
+
+  FT_LOCAL_ARRAY_DEF( char )
+  af_blue_strings[] =
+  {
+    /* */
+@AF_BLUE_STRINGS_ARRAY@
+  };
+
+
+  /* stringsets are specific to scripts */
+  FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
+  af_blue_stringsets[] =
+  {
+    /* */
+@AF_BLUE_STRINGSETS_ARRAY@
+  };
+
+
+/* END */
diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
new file mode 100644
index 0000000..d488f3f
--- /dev/null
+++ b/src/autofit/afblue.dat
@@ -0,0 +1,218 @@
+//  afblue.dat
+//
+//    Auto-fitter data for blue strings.
+//
+//  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.
+
+
+// This file contains data specific to blue zones.  It gets processed by
+// a script to simulate `jagged arrays', with enumeration values holding
+// offsets into the arrays.
+//
+// The format of the file is rather simple:  A section starts with three
+// labels separated by whitespace and followed by a colon (everything in a
+// single line); the first label gives the name of the enumeration template,
+// the second the name of the array template, and the third the name of the
+// `maximum' template, holding the size of the largest array element.  The
+// script then fills the corresponding templates (indicated by `@'
+// characters around the name).
+//
+// A section contains one or more data records.  Each data record consists
+// of two or more lines.  The first line holds the enumeration name, and the
+// remaining lines the corresponding array data.
+//
+// There are two possible representations for array data.
+//
+// - A string of characters in UTF-8 encoding enclosed in double quotes,
+//   using C syntax.  There can be only one string per line, thus the
+//   starting and ending double quote must be the first and last character
+//   in the line, respectively, ignoring whitespace before and after the
+//   string.  If there are multiple strings (in multiple lines), they are
+//   concatenated to a single string.  In the output, a string gets
+//   represented as a series of singles bytes, followed by a zero byte.  The
+//   enumeration values simply hold byte offsets to the start of the
+//   corresponding strings.
+//
+// - Data blocks enclosed in balanced braces, which get copied verbatim and
+//   which can span multiple lines.  The opening brace of a block must be
+//   the first character of a line (ignoring whitespace), and the closing
+//   brace the last (ignoring whitespace also).  The script appends a comma
+//   character after each block and counts the number of blocks to set the
+//   enumeration values.
+//
+// A section can contain either strings only or data blocks only.
+//
+// A comment line starts with `//'; it gets removed.  A preprocessor
+// directive line (using the standard syntax of `cpp') starts with `#' and
+// gets copied verbatim to both the enumeration and the array.  Whitespace
+// outside of a string is insignificant.
+//
+// Preprocessor directives are ignored while the script computes maximum
+// values; this essentially means that the maximum values can easily be too
+// large.  Given that the purpose of those values is to create local
+// fixed-size arrays at compile time for further processing of the blue zone
+// data, this isn't a problem.  Note the the final zero byte of a string is
+// not counted.  Note also that the count holds the number of UTF-8 encoded
+// characters, not bytes.
+
+
+AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+
+  AF_BLUE_STRING_LATIN_CAPITAL_TOP
+    "THEZOCQS"
+  AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
+    "HEZLOCUS"
+  AF_BLUE_STRING_LATIN_SMALL_F_TOP
+    "fijkdbh"
+  AF_BLUE_STRING_LATIN_SMALL
+    "xzroesc"
+  AF_BLUE_STRING_LATIN_SMALL_DESCENDER
+    "pqgjy"
+
+  AF_BLUE_STRING_GREEK_CAPITAL_TOP
+    "ΓΒΕΖΘΟΩ"
+  AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
+    "ΒΔΖΞΘΟ"
+  AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
+    "βθδζλξ"
+  AF_BLUE_STRING_GREEK_SMALL
+    "αειοπστω"
+  AF_BLUE_STRING_GREEK_SMALL_DESCENDER
+    "βγημρφχψ"
+
+  AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
+    "БВЕПЗОСЭ"
+  AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
+    "БВЕШЗОСЭ"
+  AF_BLUE_STRING_CYRILLIC_SMALL
+    "хпншезос"
+  AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
+    "руф"
+
+  AF_BLUE_STRING_HEBREW_TOP
+    "בדהחךכםס"
+  AF_BLUE_STRING_HEBREW_BOTTOM
+    "בטכםסצ"
+  AF_BLUE_STRING_HEBREW_DESCENDER
+    "קךןףץ"
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+  AF_BLUE_STRING_CJK_TOP_FILL
+    "他们你來們到和地"
+    "对對就席我时時會"
+    "来為能舰說说这這"
+    "齊"
+  AF_BLUE_STRING_CJK_TOP_UNFILL
+    "军同已愿既星是景"
+    "民照现現理用置要"
+    "軍那配里開雷露面"
+    "顾"
+  AF_BLUE_STRING_CJK_BOTTOM_FILL
+    "个为人他以们你來"
+    "個們到和大对對就"
+    "我时時有来為要說"
+    "说"
+  AF_BLUE_STRING_CJK_BOTTOM_UNFILL
+    "主些因它想意理生"
+    "當看着置者自著裡"
+    "过还进進過道還里"
+    "面"
+
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
+  AF_BLUE_STRING_CJK_LEFT_FILL
+    "些们你來們到和地"
+    "她将將就年得情最"
+    "样樣理能說说这這"
+    "通"
+  AF_BLUE_STRING_CJK_LEFT_UNFILL
+    "即吗吧听呢品响嗎"
+    "师師收断斷明眼間"
+    "间际陈限除陳随際"
+    "隨"
+  AF_BLUE_STRING_CJK_RIGHT_FILL
+    "事前學将將情想或"
+    "政斯新样樣民沒没"
+    "然特现現球第經谁"
+    "起"
+  AF_BLUE_STRING_CJK_RIGHT_UNFILL
+    "例別别制动動吗嗎"
+    "增指明朝期构物确"
+    "种調调費费那都間"
+    "间"
+
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+
+  AF_BLUE_STRINGSET_LATN
+    { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SMALL,           0                                 }
+    { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_GREK
+    { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GREEK_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GREEK_SMALL,           0                                 }
+    { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_CYRL
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           0                                 }
+    { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_HEBR
+    { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
+                                       AF_BLUE_PROPERTY_LATIN_LONG   }
+    { AF_BLUE_STRING_HEBREW_BOTTOM,    0                             }
+    { AF_BLUE_STRING_HEBREW_DESCENDER, 0                             }
+    { AF_BLUE_STRING_MAX,              0                             }
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+  AF_BLUE_STRINGSET_HANI
+    { AF_BLUE_STRING_CJK_TOP_FILL,      AF_BLUE_PROPERTY_CJK_TOP |
+                                        AF_BLUE_PROPERTY_CJK_FILL    }
+    { AF_BLUE_STRING_CJK_TOP_UNFILL,    AF_BLUE_PROPERTY_CJK_TOP     }
+    { AF_BLUE_STRING_CJK_BOTTOM_FILL,   AF_BLUE_PROPERTY_CJK_FILL    }
+    { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0                            }
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    { AF_BLUE_STRING_CJK_LEFT_FILL,     AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_FILL    }
+    { AF_BLUE_STRING_CJK_LEFT_UNFILL,   AF_BLUE_PROPERTY_CJK_HORIZ   }
+    { AF_BLUE_STRING_CJK_RIGHT_FILL,    AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_RIGHT |
+                                        AF_BLUE_PROPERTY_CJK_FILL    }
+    { AF_BLUE_STRING_CJK_RIGHT_UNFILL,  AF_BLUE_PROPERTY_CJK_HORIZ |
+                                        AF_BLUE_PROPERTY_CJK_RIGHT   }
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+    { AF_BLUE_STRING_MAX,               0                            }
+
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+// END
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
new file mode 100644
index 0000000..86a3649
--- /dev/null
+++ b/src/autofit/afblue.h
@@ -0,0 +1,199 @@
+/* This file has been generated by the Perl script `afblue.pl', */
+/* using data from file `afblue.dat'.                           */
+
+/***************************************************************************/
+/*                                                                         */
+/*  afblue.h                                                               */
+/*                                                                         */
+/*    Auto-fitter data for blue strings (specification).                   */
+/*                                                                         */
+/*  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 __AFBLUE_H__
+#define __AFBLUE_H__
+
+
+FT_BEGIN_HEADER
+
+
+  /* an auxiliary macro to decode a UTF-8 character -- since we only use */
+  /* hard-coded, self-converted data, no error checking is performed     */
+#define GET_UTF8_CHAR( ch, p )                    \
+          ch = (unsigned char)*p++;               \
+          if ( ch >= 0x80 )                       \
+          {                                       \
+            FT_UInt  len;                         \
+                                                  \
+                                                  \
+            if ( ch < 0xE0 )                      \
+            {                                     \
+              len = 1;                            \
+              ch &= 0x1F;                         \
+            }                                     \
+            else if ( ch < 0xF0 )                 \
+            {                                     \
+              len = 2;                            \
+              ch &= 0x0F;                         \
+            }                                     \
+            else                                  \
+            {                                     \
+              len = 3;                            \
+              ch &= 0x07;                         \
+            }                                     \
+                                                  \
+            for ( ; len > 0; len-- )              \
+              ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+          }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    B L U E   S T R I N G S                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* At the bottommost level, we define strings for finding blue zones. */
+
+
+#define AF_BLUE_STRING_MAX_LEN  25
+
+  /* The AF_Blue_String enumeration values are offsets into the */
+  /* `af_blue_strings' array.                                   */
+
+  typedef enum  AF_Blue_String_
+  {
+    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 0,
+    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 9,
+    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 18,
+    AF_BLUE_STRING_LATIN_SMALL = 26,
+    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 34,
+    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 40,
+    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 55,
+    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 68,
+    AF_BLUE_STRING_GREEK_SMALL = 81,
+    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 98,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 115,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 132,
+    AF_BLUE_STRING_CYRILLIC_SMALL = 149,
+    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 166,
+    AF_BLUE_STRING_HEBREW_TOP = 173,
+    AF_BLUE_STRING_HEBREW_BOTTOM = 190,
+    AF_BLUE_STRING_HEBREW_DESCENDER = 203,
+    af_blue_1_1 = 213,
+#ifdef AF_CONFIG_OPTION_CJK
+    AF_BLUE_STRING_CJK_TOP_FILL = af_blue_1_1 + 1,
+    AF_BLUE_STRING_CJK_TOP_UNFILL = af_blue_1_1 + 77,
+    AF_BLUE_STRING_CJK_BOTTOM_FILL = af_blue_1_1 + 153,
+    AF_BLUE_STRING_CJK_BOTTOM_UNFILL = af_blue_1_1 + 229,
+    af_blue_1_1_1 = af_blue_1_1 + 304,
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    AF_BLUE_STRING_CJK_LEFT_FILL = af_blue_1_1_1 + 1,
+    AF_BLUE_STRING_CJK_LEFT_UNFILL = af_blue_1_1_1 + 77,
+    AF_BLUE_STRING_CJK_RIGHT_FILL = af_blue_1_1_1 + 153,
+    AF_BLUE_STRING_CJK_RIGHT_UNFILL = af_blue_1_1_1 + 229,
+    af_blue_1_2_1 = af_blue_1_1_1 + 304,
+#else
+    af_blue_1_2_1 = af_blue_1_1_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+    af_blue_1_2 = af_blue_1_2_1 + 0,
+#else
+    af_blue_1_2 = af_blue_1_2_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+    AF_BLUE_STRING_MAX   /* do not remove */
+
+  } AF_Blue_String;
+
+
+  FT_LOCAL_ARRAY( char )
+  af_blue_strings[];
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                 B L U E   S T R I N G S E T S                 *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* The next level is to group blue strings into script-specific sets. */
+
+
+  /* Properties are specific to a writing system.  We assume that a given  */
+  /* blue string can't be used in more than a single writing system, which */
+  /* is a safe bet.                                                        */
+#define AF_BLUE_PROPERTY_LATIN_TOP       ( 1 << 0 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1 << 1 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1 << 2 )
+
+#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1 << 0 )
+#define AF_BLUE_PROPERTY_CJK_TOP    ( 1 << 1 )
+#define AF_BLUE_PROPERTY_CJK_FILL   ( 1 << 2 )
+#define AF_BLUE_PROPERTY_CJK_RIGHT  AF_BLUE_PROPERTY_CJK_TOP
+
+
+#define AF_BLUE_STRINGSET_MAX_LEN  9
+
+  /* The AF_Blue_Stringset enumeration values are offsets into the */
+  /* `af_blue_stringsets' array.                                   */
+
+  typedef enum  AF_Blue_Stringset_
+  {
+    AF_BLUE_STRINGSET_LATN = 0,
+    AF_BLUE_STRINGSET_GREK = 7,
+    AF_BLUE_STRINGSET_CYRL = 14,
+    AF_BLUE_STRINGSET_HEBR = 20,
+    af_blue_2_1 = 24,
+#ifdef AF_CONFIG_OPTION_CJK
+    AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
+    af_blue_2_1_1 = af_blue_2_1 + 4,
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    af_blue_2_2_1 = af_blue_2_1_1 + 4,
+#else
+    af_blue_2_2_1 = af_blue_2_1_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+    af_blue_2_2 = af_blue_2_2_1 + 1,
+#else
+    af_blue_2_2 = af_blue_2_2_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+    AF_BLUE_STRINGSET_MAX   /* do not remove */
+
+  } AF_Blue_Stringset;
+
+
+  typedef struct  AF_Blue_StringRec_
+  {
+    AF_Blue_String  string;
+    FT_UShort       properties;
+
+  } AF_Blue_StringRec;
+
+
+  FT_LOCAL_ARRAY( AF_Blue_StringRec )
+  af_blue_stringsets[];
+
+/* */
+
+FT_END_HEADER
+
+
+#endif /* __AFBLUE_H__ */
+
+
+/* END */
diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin
new file mode 100644
index 0000000..00282c3
--- /dev/null
+++ b/src/autofit/afblue.hin
@@ -0,0 +1,142 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afblue.h                                                               */
+/*                                                                         */
+/*    Auto-fitter data for blue strings (specification).                   */
+/*                                                                         */
+/*  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 __AFBLUE_H__
+#define __AFBLUE_H__
+
+
+FT_BEGIN_HEADER
+
+
+  /* an auxiliary macro to decode a UTF-8 character -- since we only use */
+  /* hard-coded, self-converted data, no error checking is performed     */
+#define GET_UTF8_CHAR( ch, p )                    \
+          ch = (unsigned char)*p++;               \
+          if ( ch >= 0x80 )                       \
+          {                                       \
+            FT_UInt  len;                         \
+                                                  \
+                                                  \
+            if ( ch < 0xE0 )                      \
+            {                                     \
+              len = 1;                            \
+              ch &= 0x1F;                         \
+            }                                     \
+            else if ( ch < 0xF0 )                 \
+            {                                     \
+              len = 2;                            \
+              ch &= 0x0F;                         \
+            }                                     \
+            else                                  \
+            {                                     \
+              len = 3;                            \
+              ch &= 0x07;                         \
+            }                                     \
+                                                  \
+            for ( ; len > 0; len-- )              \
+              ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+          }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    B L U E   S T R I N G S                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* At the bottommost level, we define strings for finding blue zones. */
+
+
+#define AF_BLUE_STRING_MAX_LEN  @AF_BLUE_STRING_MAX_LEN@
+
+  /* The AF_Blue_String enumeration values are offsets into the */
+  /* `af_blue_strings' array.                                   */
+
+  typedef enum  AF_Blue_String_
+  {
+@AF_BLUE_STRING_ENUM@
+
+    AF_BLUE_STRING_MAX   /* do not remove */
+
+  } AF_Blue_String;
+
+
+  FT_LOCAL_ARRAY( char )
+  af_blue_strings[];
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                 B L U E   S T R I N G S E T S                 *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* The next level is to group blue strings into script-specific sets. */
+
+
+  /* Properties are specific to a writing system.  We assume that a given  */
+  /* blue string can't be used in more than a single writing system, which */
+  /* is a safe bet.                                                        */
+#define AF_BLUE_PROPERTY_LATIN_TOP       ( 1 << 0 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1 << 1 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1 << 2 )
+
+#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1 << 0 )
+#define AF_BLUE_PROPERTY_CJK_TOP    ( 1 << 1 )
+#define AF_BLUE_PROPERTY_CJK_FILL   ( 1 << 2 )
+#define AF_BLUE_PROPERTY_CJK_RIGHT  AF_BLUE_PROPERTY_CJK_TOP
+
+
+#define AF_BLUE_STRINGSET_MAX_LEN  @AF_BLUE_STRINGSET_MAX_LEN@
+
+  /* The AF_Blue_Stringset enumeration values are offsets into the */
+  /* `af_blue_stringsets' array.                                   */
+
+  typedef enum  AF_Blue_Stringset_
+  {
+@AF_BLUE_STRINGSET_ENUM@
+
+    AF_BLUE_STRINGSET_MAX   /* do not remove */
+
+  } AF_Blue_Stringset;
+
+
+  typedef struct  AF_Blue_StringRec_
+  {
+    AF_Blue_String  string;
+    FT_UShort       properties;
+
+  } AF_Blue_StringRec;
+
+
+  FT_LOCAL_ARRAY( AF_Blue_StringRec )
+  af_blue_stringsets[];
+
+/* */
+
+FT_END_HEADER
+
+
+#endif /* __AFBLUE_H__ */
+
+
+/* END */
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index f69a528..7a6f835 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -26,7 +26,7 @@
 #include FT_ADVANCES_H
 #include FT_INTERNAL_DEBUG_H
 
-#include "aftypes.h"
+#include "afglobal.h"
 #include "aflatin.h"
 
 
@@ -73,6 +73,12 @@
     AF_GlyphHintsRec  hints[1];
 
 
+    FT_TRACE5(( "\n"
+                "cjk standard widths computation (script `%s')\n"
+                "===============================================\n"
+                "\n",
+                af_script_names[metrics->root.script_class->script] ));
+
     af_glyph_hints_init( hints, face->memory );
 
     metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
@@ -86,11 +92,15 @@
       AF_Scaler         scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face,
-                                       metrics->root.clazz->standard_char );
+      glyph_index = FT_Get_Char_Index(
+                      face,
+                      metrics->root.script_class->standard_char );
       if ( glyph_index == 0 )
         goto Exit;
 
+      FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
+                  metrics->root.script_class->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;
@@ -122,11 +132,13 @@
         FT_UInt       num_widths = 0;
 
 
-        error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim );
+        error = af_latin_hints_compute_segments( hints,
+                                                 (AF_Dimension)dim );
         if ( error )
           goto Exit;
 
-        af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+        af_latin_hints_link_segments( hints,
+                                      (AF_Dimension)dim );
 
         seg   = axhints->segments;
         limit = seg + axhints->num_segments;
@@ -151,7 +163,7 @@
         }
 
         /* this also replaces multiple almost identical stem widths */
-        /* with a single one (the value 100 is heuristic) */
+        /* 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;
@@ -171,263 +183,201 @@
         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 );
   }
 
 
-#define AF_CJK_MAX_TEST_CHARACTERS  32
-
-
-  /* Each blue zone has two types of fill and unfill, this is, */
-  /* filling the entire glyph square or not.                   */
-
-  enum
-  {
-    AF_CJK_BLUE_TYPE_FILL,
-    AF_CJK_BLUE_TYPE_UNFILL,
-    AF_CJK_BLUE_TYPE_MAX
-  };
-
-
-  /* Put some common and representative Han Ideographs characters here. */
-  static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX]
-                                              [AF_CJK_BLUE_TYPE_MAX]
-                                              [AF_CJK_MAX_TEST_CHARACTERS] =
-  {
-    {
-      {
-        0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
-        0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703,
-        0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
-        0x9F4A /* top fill */
-      },
-      {
-        0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F,
-        0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981,
-        0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762,
-        0x987E /* top unfill */
-      }
-    },
-    {
-      {
-        0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86,
-        0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31,
-        0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA,
-        0x8BF4 /* bottom fill */
-      },
-      {
-        0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F,
-        0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1,
-        0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC,
-        0x9762 /* bottom unfill */
-      }
-    },
-#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
-      { {0x0000}, {0x0000} },
-      { {0x0000}, {0x0000} }
-#else
-    {
-      {
-        0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
-        0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700,
-        0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
-        0x901A /* left fill */
-      },
-      {
-        0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE,
-        0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593,
-        0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B,
-        0x96A8 /* left unfill */
-      }
-    },
-    {
-      {
-        0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216,
-        0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1,
-        0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01,
-        0x8D77 /* right fill */
-      },
-      {
-        0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE,
-        0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E,
-        0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593,
-        0x95F4 /* right unfill */
-      }
-    }
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
-  };
-
-
-  /* Calculate blue zones for all the CJK_BLUE_XXX's. */
+  /* Find all blue zones. */
 
   static void
-  af_cjk_metrics_init_blues( AF_CJKMetrics   metrics,
-                             FT_Face         face,
-                             const FT_ULong  blue_chars
-                                               [AF_CJK_BLUE_MAX]
-                                               [AF_CJK_BLUE_TYPE_MAX]
-                                               [AF_CJK_MAX_TEST_CHARACTERS] )
+  af_cjk_metrics_init_blues( AF_CJKMetrics  metrics,
+                             FT_Face        face )
   {
-    FT_Pos        fills[AF_CJK_MAX_TEST_CHARACTERS];
-    FT_Pos        flats[AF_CJK_MAX_TEST_CHARACTERS];
+    FT_Pos      fills[AF_BLUE_STRING_MAX_LEN];
+    FT_Pos      flats[AF_BLUE_STRING_MAX_LEN];
 
-    FT_Int        num_fills;
-    FT_Int        num_flats;
+    FT_Int      num_fills;
+    FT_Int      num_flats;
 
-    FT_Int        bb;
-    AF_CJKBlue    blue;
-    FT_Error      error;
-    AF_CJKAxis    axis;
-    FT_GlyphSlot  glyph = face->glyph;
+    AF_CJKBlue  blue;
+    FT_Error    error;
+    AF_CJKAxis  axis;
+    FT_Outline  outline;
+
+    AF_Blue_Stringset         bss = metrics->root.script_class->blue_stringset;
+    const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
 
 #ifdef FT_DEBUG_LEVEL_TRACE
-    FT_String*  cjk_blue_name[AF_CJK_BLUE_MAX] = {
-      (FT_String*)"top",
-      (FT_String*)"bottom",
-      (FT_String*)"left",
-      (FT_String*)"right"
+    FT_String*  cjk_blue_name[4] =
+    {
+      (FT_String*)"bottom",    /* --   , --  */
+      (FT_String*)"top",       /* --   , TOP */
+      (FT_String*)"left",      /* HORIZ, --  */
+      (FT_String*)"right"      /* HORIZ, TOP */
     };
-    FT_String*  cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = {
-      (FT_String*)"filled",
-      (FT_String*)"unfilled"
+
+    FT_String*  cjk_blue_type_name[2] =
+    {
+      (FT_String*)"unfilled",  /* --   */
+      (FT_String*)"filled"     /* FILL */
     };
 #endif
 
 
-    /* We compute the blues simply by loading each character from the */
-    /* `blue_chars[blues]' string, then computing its extreme points  */
-    /* (depending blue zone type etc.).                               */
+    /* we walk over the blue character strings as specified in the    */
+    /* script's entry in the `af_blue_stringset' array, computing its */
+    /* extremum points (depending on the string properties)           */
 
-    FT_TRACE5(( "cjk blue zones computation\n" ));
-    FT_TRACE5(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "cjk blue zones computation\n"
+                "==========================\n"
+                "\n" ));
 
-    for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
+    for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
-      FT_Int   fill_type;
-      FT_Pos*  blue_ref;
-      FT_Pos*  blue_shoot;
+      const char*  p = &af_blue_strings[bs->string];
+      FT_Pos*      blue_ref;
+      FT_Pos*      blue_shoot;
 
 
+      if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
+        axis = &metrics->axis[AF_DIMENSION_HORZ];
+      else
+        axis = &metrics->axis[AF_DIMENSION_VERT];
+
+      FT_TRACE5(( "blue zone %d:\n", axis->blue_count ));
+
       num_fills = 0;
       num_flats = 0;
 
-      for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
+      FT_TRACE5(( "  cjk blue %s/%s\n",
+                  cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) |
+                                AF_CJK_IS_TOP_BLUE( bs )   ],
+                  cjk_blue_type_name[!!AF_CJK_IS_FILLED_BLUE( bs )] ));
+
+      while ( *p )
       {
-        const FT_ULong*  p     = blue_chars[bb][fill_type];
-        const FT_ULong*  limit = p + AF_CJK_MAX_TEST_CHARACTERS;
-        FT_Bool          fill  = FT_BOOL(
-                                   fill_type == AF_CJK_BLUE_TYPE_FILL );
+        FT_ULong    ch;
+        FT_UInt     glyph_index;
+        FT_Pos      best_pos;       /* same as points.y or points.x, resp. */
+        FT_Int      best_point;
+        FT_Vector*  points;
 
 
-        FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
-                                        cjk_blue_type_name[fill_type] ));
+        GET_UTF8_CHAR( ch, p );
 
-
-        for ( ; p < limit && *p; p++ )
+        /* load the character in the face -- skip unknown or empty ones */
+        glyph_index = FT_Get_Char_Index( face, ch );
+        if ( glyph_index == 0 )
         {
-          FT_UInt     glyph_index;
-          FT_Pos      best_pos; /* same as points.y */
-          FT_Int      best_point;
-          FT_Vector*  points;
+          FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
+          continue;
+        }
+
+        error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+        outline = face->glyph->outline;
+        if ( error || outline.n_points <= 0 )
+        {
+          FT_TRACE5(( "  U+%04lX contains no outlines\n", ch ));
+          continue;
+        }
+
+        /* now compute min or max point indices and coordinates */
+        points     = outline.points;
+        best_point = -1;
+        best_pos   = 0;  /* make compiler happy */
+
+        {
+          FT_Int  nn;
+          FT_Int  first = 0;
+          FT_Int  last  = -1;
 
 
-          FT_TRACE5(( "  U+%lX...", *p ));
-
-          /* load the character in the face -- skip unknown or empty ones */
-          glyph_index = FT_Get_Char_Index( face, *p );
-          if ( glyph_index == 0 )
+          for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
           {
-            FT_TRACE5(( "unavailable\n" ));
-            continue;
-          }
-
-          error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
-          if ( error || glyph->outline.n_points <= 0 )
-          {
-            FT_TRACE5(( "no outline\n" ));
-            continue;
-          }
-
-          /* now compute min or max point indices and coordinates */
-          points     = glyph->outline.points;
-          best_point = -1;
-          best_pos   = 0;  /* make compiler happy */
-
-          {
-            FT_Int  nn;
-            FT_Int  first = 0;
-            FT_Int  last  = -1;
+            FT_Int  pp;
 
 
-            for ( nn = 0;
-                  nn < glyph->outline.n_contours;
-                  first = last + 1, nn++ )
+            last = outline.contours[nn];
+
+            /* Avoid single-point contours since they are never rasterized. */
+            /* In some fonts, they correspond to mark attachment points     */
+            /* which are way outside of the glyph's real outline.           */
+            if ( last <= first )
+              continue;
+
+            if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
             {
-              FT_Int  pp;
-
-
-              last = glyph->outline.contours[nn];
-
-              /* Avoid single-point contours since they are never       */
-              /* rasterized.  In some fonts, they correspond to mark    */
-              /* attachment points which are way outside of the glyph's */
-              /* real outline.                                          */
-              if ( last <= first )
-                continue;
-
-              switch ( bb )
+              if ( AF_CJK_IS_RIGHT_BLUE( bs ) )
               {
-              case AF_CJK_BLUE_TOP:
-                for ( pp = first; pp <= last; pp++ )
-                  if ( best_point < 0 || points[pp].y > best_pos )
-                  {
-                    best_point = pp;
-                    best_pos   = points[pp].y;
-                  }
-                break;
-
-              case AF_CJK_BLUE_BOTTOM:
-                for ( pp = first; pp <= last; pp++ )
-                  if ( best_point < 0 || points[pp].y < best_pos )
-                  {
-                    best_point = pp;
-                    best_pos   = points[pp].y;
-                  }
-                break;
-
-              case AF_CJK_BLUE_LEFT:
-                for ( pp = first; pp <= last; pp++ )
-                  if ( best_point < 0 || points[pp].x < best_pos )
-                  {
-                    best_point = pp;
-                    best_pos   = points[pp].x;
-                  }
-                break;
-
-              case AF_CJK_BLUE_RIGHT:
                 for ( pp = first; pp <= last; pp++ )
                   if ( best_point < 0 || points[pp].x > best_pos )
                   {
                     best_point = pp;
                     best_pos   = points[pp].x;
                   }
-                break;
-
-              default:
-                ;
+              }
+              else
+              {
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].x < best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].x;
+                  }
               }
             }
-            FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
+            else
+            {
+              if ( AF_CJK_IS_TOP_BLUE( bs ) )
+              {
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].y > best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].y;
+                  }
+              }
+              else
+              {
+                for ( pp = first; pp <= last; pp++ )
+                  if ( best_point < 0 || points[pp].y < best_pos )
+                  {
+                    best_point = pp;
+                    best_pos   = points[pp].y;
+                  }
+              }
+            }
           }
 
-          if ( fill )
-            fills[num_fills++] = best_pos;
-          else
-            flats[num_flats++] = best_pos;
+          FT_TRACE5(( "  U+%04lX: best_pos = %5ld\n", ch, best_pos ));
         }
+
+        if ( AF_CJK_IS_FILLED_BLUE( bs ) )
+          fills[num_fills++] = best_pos;
+        else
+          flats[num_flats++] = best_pos;
       }
 
       if ( num_flats == 0 && num_fills == 0 )
@@ -436,34 +386,30 @@
          *  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;
       }
 
       /* we have computed the contents of the `fill' and `flats' tables, */
-      /* now determine the reference position of the blue --             */
+      /* now determine the reference position of the blue zone --        */
       /* we simply take the median value after a simple sort             */
       af_sort_pos( num_flats, flats );
       af_sort_pos( num_fills, fills );
 
-      if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb )
-        axis = &metrics->axis[AF_DIMENSION_VERT];
-      else
-        axis = &metrics->axis[AF_DIMENSION_HORZ];
-
-      blue       = & axis->blues[axis->blue_count];
-      blue_ref   = & blue->ref.org;
-      blue_shoot = & blue->shoot.org;
+      blue       = &axis->blues[axis->blue_count];
+      blue_ref   = &blue->ref.org;
+      blue_shoot = &blue->shoot.org;
 
       axis->blue_count++;
+
       if ( num_flats == 0 )
       {
-        *blue_ref   = fills[num_fills / 2];
+        *blue_ref   =
         *blue_shoot = fills[num_fills / 2];
       }
       else if ( num_fills == 0 )
       {
-        *blue_ref   = flats[num_flats / 2];
+        *blue_ref   =
         *blue_shoot = flats[num_flats / 2];
       }
       else
@@ -481,26 +427,34 @@
         FT_Bool  under_ref = FT_BOOL( shoot < ref );
 
 
-        if ( ( AF_CJK_BLUE_TOP == bb   ||
-               AF_CJK_BLUE_RIGHT == bb ) ^ under_ref )
-          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+        /* AF_CJK_IS_TOP_BLUE covers `right' and `top' */
+        if ( AF_CJK_IS_TOP_BLUE( bs ) ^ under_ref )
+        {
+          *blue_ref   =
+          *blue_shoot = ( shoot + ref ) / 2;
+
+          FT_TRACE5(( "  [overshoot smaller than reference,"
+                      " taking mean value]\n" ));
+        }
       }
 
       blue->flags = 0;
-      if ( AF_CJK_BLUE_TOP == bb )
-        blue->flags |= AF_CJK_BLUE_IS_TOP;
-      else if ( AF_CJK_BLUE_RIGHT == bb )
-        blue->flags |= AF_CJK_BLUE_IS_RIGHT;
+      if ( AF_CJK_IS_TOP_BLUE( bs ) )
+        blue->flags |= AF_CJK_BLUE_TOP;
 
-      FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n",
-                  cjk_blue_name[bb], *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "    -> reference = %ld\n"
+                  "       overshoot = %ld\n",
+                  *blue_ref, *blue_shoot ));
     }
 
+    FT_TRACE5(( "\n" ));
+
     return;
   }
 
 
   /* Basically the Latin version with type AF_CJKMetrics for metrics. */
+
   FT_LOCAL_DEF( void )
   af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
                                FT_Face        face )
@@ -510,8 +464,7 @@
     FT_Fixed  advance, old_advance = 0;
 
 
-    /* check whether all ASCII digits have the same advance width; */
-    /* digit `0' is 0x30 in all supported charmaps                 */
+    /* digit `0' is 0x30 in all supported charmaps */
     for ( i = 0x30; i <= 0x39; i++ )
     {
       FT_UInt  glyph_index;
@@ -547,6 +500,8 @@
   }
 
 
+  /* Initialize global metrics. */
+
   FT_LOCAL_DEF( FT_Error )
   af_cjk_metrics_init( AF_CJKMetrics  metrics,
                        FT_Face        face )
@@ -556,21 +511,21 @@
 
     metrics->units_per_em = face->units_per_EM;
 
-    if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
-      face->charmap = NULL;
-    else
+    if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
     {
       af_cjk_metrics_init_widths( metrics, face );
-      af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
+      af_cjk_metrics_init_blues( metrics, face );
       af_cjk_metrics_check_digits( metrics, face );
     }
 
     FT_Set_Charmap( face, oldmap );
-
     return FT_Err_Ok;
   }
 
 
+  /* Adjust scaling value, then scale and shift widths   */
+  /* and blue zones (if applicable) for given dimension. */
+
   static void
   af_cjk_metrics_scale_dim( AF_CJKMetrics  metrics,
                             AF_Scaler      scaler,
@@ -582,8 +537,6 @@
     FT_UInt     nn;
 
 
-    axis = &metrics->axis[dim];
-
     if ( dim == AF_DIMENSION_HORZ )
     {
       scale = scaler->x_scale;
@@ -595,6 +548,8 @@
       delta = scaler->y_delta;
     }
 
+    axis = &metrics->axis[dim];
+
     if ( axis->org_scale == scale && axis->org_delta == delta )
       return;
 
@@ -650,12 +605,13 @@
 
         blue->shoot.fit = blue->ref.fit - delta2;
 
-        FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: "
-                     "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n",
-                       ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
-                       nn, blue->ref.org, blue->shoot.org,
-                       blue->ref.cur / 64.0, blue->ref.fit / 64.0,
-                       blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+        FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
+                    "     ref:   cur=%.2f fit=%.2f\n"
+                    "     shoot: cur=%.2f fit=%.2f\n",
+                    ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
+                    nn, blue->ref.org, blue->shoot.org,
+                    blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+                    blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
 
         blue->flags |= AF_CJK_BLUE_ACTIVE;
       }
@@ -663,10 +619,14 @@
   }
 
 
+  /* Scale global values in both directions. */
+
   FT_LOCAL_DEF( void )
   af_cjk_metrics_scale( AF_CJKMetrics  metrics,
                         AF_Scaler      scaler )
   {
+    /* we copy the whole structure since the x and y scaling values */
+    /* are not modified, contrary to e.g. the `latin' auto-hinter   */
     metrics->root.scaler = *scaler;
 
     af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
@@ -682,6 +642,9 @@
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Walk over all contours and compute its segments. */
+
   static FT_Error
   af_cjk_hints_compute_segments( AF_GlyphHints  hints,
                                  AF_Dimension   dim )
@@ -938,7 +901,7 @@
 
     for ( seg = segments; seg < segment_limit; seg++ )
     {
-      AF_Edge  found = 0;
+      AF_Edge  found = NULL;
       FT_Pos   best  = 0xFFFFU;
       FT_Int   ee;
 
@@ -1026,25 +989,26 @@
       }
     }
 
-    /*********************************************************************/
-    /*                                                                   */
-    /* Good, we now compute each edge's properties according to segments */
-    /* found on its position.  Basically, these are as follows.          */
-    /*                                                                   */
-    /*  - 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                           */
-    /*                                                                   */
-    /* Note that removing this loop and setting the `edge' field of each */
-    /* segment directly in the code above slows down execution speed for */
-    /* some reasons on platforms like the Sun.                           */
+    /* first of all, set the `edge' field in each segment -- this is */
+    /* required in order to compute edge links                       */
 
+    /*
+     * Note that removing this loop and setting the `edge' field of each
+     * segment directly in the code above slows down execution speed for
+     * some reasons on platforms like the Sun.
+     */
     {
       AF_Edge  edges      = axis->edges;
       AF_Edge  edge_limit = edges + axis->num_edges;
@@ -1153,6 +1117,8 @@
   }
 
 
+  /* Detect segments and edges for given dimension. */
+
   static FT_Error
   af_cjk_hints_detect_features( AF_GlyphHints  hints,
                                 AF_Dimension   dim )
@@ -1171,6 +1137,8 @@
   }
 
 
+  /* Compute all edges which lie within blue zones. */
+
   FT_LOCAL_DEF( void )
   af_cjk_hints_compute_blue_edges( AF_GlyphHints  hints,
                                    AF_CJKMetrics  metrics,
@@ -1218,10 +1186,8 @@
         /* zone, check for left edges                                      */
         /*                                                                 */
         /* of course, that's for TrueType                                  */
-        is_top_right_blue  =
-          FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP )   != 0 ) ||
-                   ( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) );
-        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+        is_top_right_blue = FT_BOOL( blue->flags & AF_CJK_BLUE_TOP );
+        is_major_dir      = FT_BOOL( edge->dir == axis->major_dir );
 
         /* if it is a top zone, the edge must be against the major    */
         /* direction; if it is a bottom zone, it must be in the major */
@@ -1258,6 +1224,8 @@
   }
 
 
+  /* Initalize hinting engine. */
+
   FT_LOCAL_DEF( FT_Error )
   af_cjk_hints_init( AF_GlyphHints  hints,
                      AF_CJKMetrics  metrics )
@@ -1316,7 +1284,7 @@
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
-    return 0;
+    return FT_Err_Ok;
   }
 
 
@@ -1328,8 +1296,8 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  /* snap a given width in scaled coordinates to one of the */
-  /* current standard widths                                */
+  /* Snap a given width in scaled coordinates to one of the */
+  /* current standard widths.                               */
 
   static FT_Pos
   af_cjk_snap_width( AF_Width  widths,
@@ -1376,7 +1344,9 @@
   }
 
 
-  /* compute the snapped width of a given stem */
+  /* Compute the snapped width of a given stem.                          */
+  /* There is a lot of voodoo in this function; changing the hard-coded  */
+  /* parameters influence the whole hinting process.                     */
 
   static FT_Pos
   af_cjk_compute_stem_width( AF_GlyphHints  hints,
@@ -1385,8 +1355,8 @@
                              AF_Edge_Flags  base_flags,
                              AF_Edge_Flags  stem_flags )
   {
-    AF_CJKMetrics  metrics  = (AF_CJKMetrics) hints->metrics;
-    AF_CJKAxis     axis     = & metrics->axis[dim];
+    AF_CJKMetrics  metrics  = (AF_CJKMetrics)hints->metrics;
+    AF_CJKAxis     axis     = &metrics->axis[dim];
     FT_Pos         dist     = width;
     FT_Int         sign     = 0;
     FT_Bool        vertical = FT_BOOL( dim == AF_DIMENSION_VERT );
@@ -1497,7 +1467,7 @@
   }
 
 
-  /* align one stem edge relative to the previous stem edge */
+  /* Align one stem edge relative to the previous stem edge. */
 
   static void
   af_cjk_align_linked_edge( AF_GlyphHints  hints,
@@ -1517,6 +1487,9 @@
   }
 
 
+  /* Shift the coordinates of the `serif' edge by the same amount */
+  /* as the corresponding `base' edge has been moved already.     */
+
   static void
   af_cjk_align_serif_edge( AF_GlyphHints  hints,
                            AF_Edge        base,
@@ -1670,6 +1643,8 @@
   }
 
 
+  /* The main grid-fitting routine. */
+
   static void
   af_cjk_hint_edges( AF_GlyphHints  hints,
                      AF_Dimension   dim )
@@ -1685,10 +1660,16 @@
     FT_Bool       has_last_stem = FALSE;
     FT_Pos        last_stem_pos = 0;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+    FT_UInt       num_actions = 0;
+#endif
+
+
+    FT_TRACE5(( "cjk %s edge hinting (script `%s')\n",
+                dim == AF_DIMENSION_VERT ? "horizontal" : "vertical",
+                af_script_names[hints->metrics->script_class->script] ));
 
     /* we begin by aligning all stems relative to the blue zone */
-    FT_TRACE5(( "==== cjk hinting %s edges =====\n",
-          dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
 
     if ( AF_HINTS_DO_BLUES( hints ) )
     {
@@ -1719,10 +1700,14 @@
         if ( !edge1 )
           continue;
 
-        FT_TRACE5(( "CJKBLUE: edge %d @%d (opos=%.2f) snapped to (%.2f), "
-                 "was (%.2f)\n",
-                 edge1-edges, edge1->fpos, edge1->opos / 64.0, blue->fit / 64.0,
-                 edge1->pos / 64.0 ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+        FT_TRACE5(( "  CJKBLUE: edge %d @%d (opos=%.2f) snapped to %.2f,"
+                    " was %.2f\n",
+                    edge1 - edges, edge1->fpos, edge1->opos / 64.0,
+                    blue->fit / 64.0, edge1->pos / 64.0 ));
+
+        num_actions++;
+#endif
 
         edge1->pos    = blue->fit;
         edge1->flags |= AF_EDGE_DONE;
@@ -1731,6 +1716,10 @@
         {
           af_cjk_align_linked_edge( hints, dim, edge1, edge2 );
           edge2->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          num_actions++;
+#endif
         }
 
         if ( !anchor )
@@ -1772,6 +1761,7 @@
       }
 
       /* now align the stem */
+
       /* this should not happen, but it's better to be safe */
       if ( edge2->blue_edge )
       {
@@ -1779,6 +1769,11 @@
 
         af_cjk_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions++;
+#endif
+
         continue;
       }
 
@@ -1786,6 +1781,11 @@
       {
         af_cjk_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions++;
+#endif
+
         /* We rarely reaches here it seems;
          * usually the two edges belonging
          * to one stem are marked as DONE together
@@ -1953,7 +1953,7 @@
     }
 
     if ( !skipped )
-      return;
+      goto Exit;
 
     /*
      *  now hint the remaining edges (serifs and single) in order
@@ -1973,7 +1973,7 @@
     }
 
     if ( !skipped )
-      return;
+      goto Exit;
 
     for ( edge = edges; edge < edge_limit; edge++ )
     {
@@ -2011,6 +2011,16 @@
         }
       }
     }
+
+  Exit:
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( !num_actions )
+      FT_TRACE5(( "  (none)\n" ));
+    FT_TRACE5(( "\n" ));
+#endif
+
+    return;
   }
 
 
@@ -2104,6 +2114,8 @@
   }
 
 
+  /* Apply the complete hinting algorithm to a CJK glyph. */
+
   FT_LOCAL_DEF( FT_Error )
   af_cjk_hints_apply( AF_GlyphHints  hints,
                       FT_Outline*    outline,
@@ -2191,9 +2203,28 @@
   /*************************************************************************/
 
 
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_cjk_writing_system_class,
+
+    AF_WRITING_SYSTEM_CJK,
+
+    sizeof ( AF_CJKMetricsRec ),
+
+    (AF_Script_InitMetricsFunc) af_cjk_metrics_init,
+    (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
+    (AF_Script_DoneMetricsFunc) NULL,
+
+    (AF_Script_InitHintsFunc)   af_cjk_hints_init,
+    (AF_Script_ApplyHintsFunc)  af_cjk_hints_apply
+  )
+
+
   /* this corresponds to Unicode 6.0 */
 
-  static const AF_Script_UniRangeRec  af_cjk_uniranges[] =
+  /* XXX: this should probably fine tuned to differentiate better between */
+  /*      scripts...                                                      */
+
+  static const AF_Script_UniRangeRec  af_hani_uniranges[] =
   {
     AF_UNIRANGE_REC(  0x1100UL,  0x11FFUL ),  /* Hangul Jamo                             */
     AF_UNIRANGE_REC(  0x2E80UL,  0x2EFFUL ),  /* CJK Radicals Supplement                 */
@@ -2231,33 +2262,12 @@
   };
 
 
-  AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
-    AF_SCRIPT_CJK,
-    af_cjk_uniranges,
-    0x7530, /* 田 */
-
-    sizeof ( AF_CJKMetricsRec ),
-
-    (AF_Script_InitMetricsFunc) af_cjk_metrics_init,
-    (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
-    (AF_Script_DoneMetricsFunc) NULL,
-
-    (AF_Script_InitHintsFunc)   af_cjk_hints_init,
-    (AF_Script_ApplyHintsFunc)  af_cjk_hints_apply
-  )
-
 #else /* !AF_CONFIG_OPTION_CJK */
 
-  static const AF_Script_UniRangeRec  af_cjk_uniranges[] =
-  {
-    AF_UNIRANGE_REC( 0UL, 0UL )
-  };
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_cjk_writing_system_class,
 
-
-  AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
-    AF_SCRIPT_CJK,
-    af_cjk_uniranges,
-    0,
+    AF_WRITING_SYSTEM_CJK,
 
     sizeof ( AF_CJKMetricsRec ),
 
@@ -2269,7 +2279,25 @@
     (AF_Script_ApplyHintsFunc)  NULL
   )
 
+
+  static const AF_Script_UniRangeRec  af_hani_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0UL, 0UL )
+  };
+
 #endif /* !AF_CONFIG_OPTION_CJK */
 
 
+  AF_DEFINE_SCRIPT_CLASS(
+    af_hani_script_class,
+
+    AF_SCRIPT_HANI,
+    AF_BLUE_STRINGSET_HANI,
+    AF_WRITING_SYSTEM_CJK,
+
+    af_hani_uniranges,
+    0x7530 /* 田 */
+  )
+
+
 /* END */
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index ab816f2..6f5bdc5 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, 2012 by                                    */
+/*  Copyright 2006, 2007, 2011-2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,39 +26,48 @@
 FT_BEGIN_HEADER
 
 
-  /* the CJK-specific script class */
+  /* the CJK-specific writing system */
 
-  AF_DECLARE_SCRIPT_CLASS( af_cjk_script_class )
+  AF_DECLARE_WRITING_SYSTEM_CLASS( af_cjk_writing_system_class )
 
-  /* CJK (global) metrics management */
+
+  /* the CJK-specific script classes */
+
+  AF_DECLARE_SCRIPT_CLASS( af_hani_script_class )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****              C J K   G L O B A L   M E T R I C S              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
 
   /*
    *  CJK glyphs tend to fill the square.  So we have both vertical and
    *  horizontal blue zones.  But some glyphs have flat bounding strokes that
    *  leave some space between neighbour glyphs.
    */
-  enum
-  {
-    AF_CJK_BLUE_TOP,
-    AF_CJK_BLUE_BOTTOM,
-    AF_CJK_BLUE_LEFT,
-    AF_CJK_BLUE_RIGHT,
 
-    AF_CJK_BLUE_MAX
-  };
-
+#define AF_CJK_IS_TOP_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP )
+#define AF_CJK_IS_HORIZ_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ )
+#define AF_CJK_IS_FILLED_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_CJK_FILL )
+#define AF_CJK_IS_RIGHT_BLUE  AF_CJK_IS_TOP_BLUE
 
 #define AF_CJK_MAX_WIDTHS  16
-#define AF_CJK_MAX_BLUES   AF_CJK_BLUE_MAX
 
 
   enum
   {
-    AF_CJK_BLUE_ACTIVE     = 1 << 0,
-    AF_CJK_BLUE_IS_TOP     = 1 << 1,
-    AF_CJK_BLUE_IS_RIGHT   = 1 << 2,
-    AF_CJK_BLUE_ADJUSTMENT = 1 << 3,  /* used for scale adjustment */
-                                      /* optimization              */
+    AF_CJK_BLUE_ACTIVE     = 1 << 0,  /* set if zone height is <= 3/4px */
+    AF_CJK_BLUE_TOP        = 1 << 1,  /* result of AF_CJK_IS_TOP_BLUE   */
+    AF_CJK_BLUE_ADJUSTMENT = 1 << 2,  /* used for scale adjustment      */
+                                      /* optimization                   */
     AF_CJK_BLUE_FLAG_MAX
   };
 
@@ -77,16 +86,16 @@
     FT_Fixed       scale;
     FT_Pos         delta;
 
-    FT_UInt        width_count;
-    AF_WidthRec    widths[AF_CJK_MAX_WIDTHS];
-    FT_Pos         edge_distance_threshold;
-    FT_Pos         standard_width;
-    FT_Bool        extra_light;
+    FT_UInt        width_count;                   /* number of used widths */
+    AF_WidthRec    widths[AF_CJK_MAX_WIDTHS];     /* widths array          */
+    FT_Pos         edge_distance_threshold;     /* used for creating edges */
+    FT_Pos         standard_width;           /* the default stem thickness */
+    FT_Bool        extra_light;           /* is standard width very light? */
 
     /* used for horizontal metrics too for CJK */
     FT_Bool        control_overshoot;
     FT_UInt        blue_count;
-    AF_CJKBlueRec  blues[AF_CJK_BLUE_MAX];
+    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX];
 
     FT_Fixed       org_scale;
     FT_Pos         org_delta;
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 2294455..b2b3a20 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -26,8 +26,13 @@
   af_dummy_hints_init( AF_GlyphHints     hints,
                        AF_ScriptMetrics  metrics )
   {
-    af_glyph_hints_rescale( hints,
-                            metrics );
+    af_glyph_hints_rescale( hints, metrics );
+
+    hints->x_scale = metrics->scaler.x_scale;
+    hints->y_scale = metrics->scaler.y_scale;
+    hints->x_delta = metrics->scaler.x_delta;
+    hints->y_delta = metrics->scaler.y_delta;
+
     return FT_Err_Ok;
   }
 
@@ -36,17 +41,21 @@
   af_dummy_hints_apply( AF_GlyphHints  hints,
                         FT_Outline*    outline )
   {
-    FT_UNUSED( hints );
-    FT_UNUSED( outline );
+    FT_Error  error;
 
-    return FT_Err_Ok;
+
+    error = af_glyph_hints_reload( hints, outline );
+    if ( !error )
+      af_glyph_hints_save( hints, outline );
+
+    return error;
   }
 
 
-  AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
-    AF_SCRIPT_DUMMY,
-    NULL,
-    0,
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_dummy_writing_system_class,
+
+    AF_WRITING_SYSTEM_DUMMY,
 
     sizeof ( AF_ScriptMetricsRec ),
 
@@ -59,4 +68,16 @@
   )
 
 
+  AF_DEFINE_SCRIPT_CLASS(
+    af_none_script_class,
+
+    AF_SCRIPT_NONE,
+    (AF_Blue_Stringset)0,
+    AF_WRITING_SYSTEM_DUMMY,
+
+    NULL,
+    '\0'
+  )
+
+
 /* END */
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index 95d8f8c..9a4d3c2 100644
--- a/src/autofit/afdummy.h
+++ b/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter dummy routines to be used if no hinting should be        */
 /*    performed (specification).                                           */
 /*                                                                         */
-/*  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,       */
@@ -25,11 +25,13 @@
 
 FT_BEGIN_HEADER
 
- /*  A dummy script metrics class used when no hinting should
-  *  be performed.  This is the default for non-latin glyphs!
+ /*  A dummy writing system and script class used when no hinting should be
+  *  performed.
   */
 
-  AF_DECLARE_SCRIPT_CLASS( af_dummy_script_class )
+  AF_DECLARE_WRITING_SYSTEM_CLASS( af_dummy_writing_system_class )
+
+  AF_DECLARE_SCRIPT_CLASS( af_none_script_class )
 
 /* */
 
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 3e41465..c2151af 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -17,39 +17,64 @@
 
 
 #include "afglobal.h"
-#include "afdummy.h"
-#include "aflatin.h"
-#include "afcjk.h"
-#include "afindic.h"
-#include "afpic.h"
+
+  /* get writing system specific header files */
+#undef  WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS )  /* empty */
+#include "afwrtsys.h"
 
 #include "aferrors.h"
+#include "afpic.h"
 
-#ifdef FT_OPTION_AUTOFIT2
-#include "aflatin2.h"
-#endif
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-  /* when updating this table, don't forget to update          */
-  /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
+#undef  WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS )               \
+          &af_ ## ws ## _writing_system_class,
 
-  /* populate this list when you add new scripts */
-  static AF_ScriptClass const  af_script_classes[] =
+  FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass )
+  af_writing_system_classes[] =
   {
-    &af_dummy_script_class,
-#ifdef FT_OPTION_AUTOFIT2
-    &af_latin2_script_class,
-#endif
-    &af_latin_script_class,
-    &af_cjk_script_class,
-    &af_indic_script_class,
+
+#include "afwrtsys.h"
+
+    NULL  /* do not remove */
+  };
+
+
+#undef  SCRIPT
+#define SCRIPT( s, S, d )             \
+          &af_ ## s ## _script_class,
+
+  FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
+  af_script_classes[] =
+  {
+
+#include "afscript.h"
+
     NULL  /* do not remove */
   };
 
 #endif /* !FT_CONFIG_OPTION_PIC */
 
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#undef  SCRIPT
+#define SCRIPT( s, S, d )  #s,
+
+  FT_LOCAL_ARRAY_DEF( char* )
+  af_script_names[] =
+  {
+
+#include "afscript.h"
+
+  };
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
   /* Compute the script index of each glyph within a given face. */
 
   static FT_Error
@@ -63,9 +88,9 @@
     FT_UInt     i;
 
 
-    /* the value AF_SCRIPT_NONE means `uncovered glyph' */
+    /* the value AF_SCRIPT_UNASSIGNED means `uncovered glyph' */
     FT_MEM_SET( globals->glyph_scripts,
-                AF_SCRIPT_NONE,
+                AF_SCRIPT_UNASSIGNED,
                 globals->glyph_count );
 
     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
@@ -82,18 +107,20 @@
     /* scan each script in a Unicode charmap */
     for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
     {
-      AF_ScriptClass      clazz = AF_SCRIPT_CLASSES_GET[ss];
+      AF_ScriptClass      script_class = AF_SCRIPT_CLASSES_GET[ss];
       AF_Script_UniRange  range;
 
 
-      if ( clazz->script_uni_ranges == NULL )
+      if ( script_class->script_uni_ranges == NULL )
         continue;
 
       /*
        *  Scan all Unicode points in the range and set the corresponding
        *  glyph script index.
        */
-      for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
+      for ( range = script_class->script_uni_ranges;
+            range->first != 0;
+            range++ )
       {
         FT_ULong  charcode = range->first;
         FT_UInt   gindex;
@@ -101,9 +128,9 @@
 
         gindex = FT_Get_Char_Index( face, charcode );
 
-        if ( gindex != 0                             &&
-             gindex < (FT_ULong)globals->glyph_count &&
-             gscripts[gindex] == AF_SCRIPT_NONE )
+        if ( gindex != 0                              &&
+             gindex < (FT_ULong)globals->glyph_count  &&
+             gscripts[gindex] == AF_SCRIPT_UNASSIGNED )
           gscripts[gindex] = (FT_Byte)ss;
 
         for (;;)
@@ -113,8 +140,8 @@
           if ( gindex == 0 || charcode > range->last )
             break;
 
-          if ( gindex < (FT_ULong)globals->glyph_count &&
-               gscripts[gindex] == AF_SCRIPT_NONE )
+          if ( gindex < (FT_ULong)globals->glyph_count  &&
+               gscripts[gindex] == AF_SCRIPT_UNASSIGNED )
             gscripts[gindex] = (FT_Byte)ss;
         }
       }
@@ -135,16 +162,16 @@
      *  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 )
+    if ( globals->module->fallback_script != AF_SCRIPT_UNASSIGNED )
     {
       FT_Long  nn;
 
 
       for ( nn = 0; nn < globals->glyph_count; nn++ )
       {
-        if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_NONE )
+        if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_UNASSIGNED )
         {
-          gscripts[nn] &= ~AF_SCRIPT_NONE;
+          gscripts[nn] &= ~AF_SCRIPT_UNASSIGNED;
           gscripts[nn] |= globals->module->fallback_script;
         }
       }
@@ -204,13 +231,14 @@
       {
         if ( globals->metrics[nn] )
         {
-          AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
+          AF_ScriptClass         script_class =
+            AF_SCRIPT_CLASSES_GET[nn];
+          AF_WritingSystemClass  writing_system_class =
+            AF_WRITING_SYSTEM_CLASSES_GET[script_class->writing_system];
 
 
-          FT_ASSERT( globals->metrics[nn]->clazz == clazz );
-
-          if ( clazz->script_metrics_done )
-            clazz->script_metrics_done( globals->metrics[nn] );
+          if ( writing_system_class->script_metrics_done )
+            writing_system_class->script_metrics_done( globals->metrics[nn] );
 
           FT_FREE( globals->metrics[nn] );
         }
@@ -232,12 +260,12 @@
                                AF_ScriptMetrics  *ametrics )
   {
     AF_ScriptMetrics  metrics = NULL;
-    FT_UInt           gidx;
-    AF_ScriptClass    clazz;
-    FT_UInt           script     = options & 15;
-    const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
-                                     sizeof ( AF_SCRIPT_CLASSES_GET[0] );
-    FT_Error          error      = FT_Err_Ok;
+
+    AF_Script              script = (AF_Script)( options & 15 );
+    AF_WritingSystemClass  writing_system_class;
+    AF_ScriptClass         script_class;
+
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( gindex >= (FT_ULong)globals->glyph_count )
@@ -246,41 +274,44 @@
       goto Exit;
     }
 
-    gidx = script;
-    if ( gidx == 0 || gidx + 1 >= script_max )
-      gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_NONE;
+    /* if we have a forced script (via `options'), use it, */
+    /* otherwise look into `glyph_scripts' array           */
+    if ( script == AF_SCRIPT_NONE || script + 1 >= AF_SCRIPT_MAX )
+      script = (AF_Script)( globals->glyph_scripts[gindex] &
+                            AF_SCRIPT_UNASSIGNED           );
 
-    clazz = AF_SCRIPT_CLASSES_GET[gidx];
-    if ( script == 0 )
-      script = clazz->script;
+    script_class         = AF_SCRIPT_CLASSES_GET[script];
+    writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET
+                             [script_class->writing_system];
 
-    metrics = globals->metrics[clazz->script];
+    metrics = globals->metrics[script];
     if ( metrics == NULL )
     {
       /* create the global metrics object if necessary */
       FT_Memory  memory = globals->face->memory;
 
 
-      if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
+      if ( FT_ALLOC( metrics, writing_system_class->script_metrics_size ) )
         goto Exit;
 
-      metrics->clazz   = clazz;
-      metrics->globals = globals;
+      metrics->script_class = script_class;
+      metrics->globals      = globals;
 
-      if ( clazz->script_metrics_init )
+      if ( writing_system_class->script_metrics_init )
       {
-        error = clazz->script_metrics_init( metrics, globals->face );
+        error = writing_system_class->script_metrics_init( metrics,
+                                                           globals->face );
         if ( error )
         {
-          if ( clazz->script_metrics_done )
-            clazz->script_metrics_done( metrics );
+          if ( writing_system_class->script_metrics_done )
+            writing_system_class->script_metrics_done( metrics );
 
           FT_FREE( metrics );
           goto Exit;
         }
       }
 
-      globals->metrics[clazz->script] = metrics;
+      globals->metrics[script] = metrics;
     }
 
   Exit:
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 2e24900..c01b474 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-2012 by                          */
+/*  Copyright 2003-2005, 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,       */
@@ -28,17 +28,32 @@
 FT_BEGIN_HEADER
 
 
+  FT_LOCAL_ARRAY( AF_WritingSystemClass )
+  af_writing_system_classes[];
+
+  FT_LOCAL_ARRAY( AF_ScriptClass )
+  af_script_classes[];
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+  FT_LOCAL_ARRAY( char* )
+  af_script_names[];
+#endif
+
   /*
    *  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
+#ifdef AF_CONFIG_OPTION_CJK
+#define AF_SCRIPT_FALLBACK  AF_SCRIPT_HANI
+#else
+#define AF_SCRIPT_FALLBACK  AF_SCRIPT_NONE
+#endif
   /* a bit mask indicating an uncovered glyph        */
-#define AF_SCRIPT_NONE      0x7F
+#define AF_SCRIPT_UNASSIGNED  0x7F
   /* if this flag is set, we have an ASCII digit     */
-#define AF_DIGIT            0x80
+#define AF_DIGIT              0x80
 
   /* `increase-x-height' property */
 #define AF_PROP_INCREASE_X_HEIGHT_MIN  6
@@ -55,8 +70,8 @@
 
 
   /*
-   *  Note that glyph_scripts[] is used to map each glyph into
-   *  an index into the `af_script_classes' array.
+   *  Note that glyph_scripts[] maps each glyph to an index into the
+   *  `af_script_classes' array.
    *
    */
   typedef struct  AF_FaceGlobalsRec_
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index e8defaa..ce504cc 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -144,6 +144,17 @@
 
 #include FT_CONFIG_STANDARD_LIBRARY_H
 
+  /* The dump functions are used in the `ftgrid' demo program, too. */
+#define AF_DUMP( varformat )          \
+          do                          \
+          {                           \
+            if ( to_stdout )          \
+              printf varformat;       \
+            else                      \
+              FT_TRACE7( varformat ); \
+          } while ( 0 )
+
+
   static const char*
   af_dir_str( AF_Direction  dir )
   {
@@ -179,34 +190,35 @@
   extern "C" {
 #endif
   void
-  af_glyph_hints_dump_points( AF_GlyphHints  hints )
+  af_glyph_hints_dump_points( AF_GlyphHints  hints,
+                              FT_Bool        to_stdout )
   {
     AF_Point  points = hints->points;
     AF_Point  limit  = points + hints->num_points;
     AF_Point  point;
 
 
-    FT_TRACE7(( "Table of points:\n"
-                "  [ index |  xorg |  yorg | xscale | yscale"
-                " |  xfit |  yfit |  flags ]\n" ));
+    AF_DUMP(( "Table of points:\n"
+              "  [ index |  xorg |  yorg | xscale | yscale"
+              " |  xfit |  yfit |  flags ]\n" ));
 
     for ( point = points; point < limit; point++ )
-      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" ));
+      AF_DUMP(( "  [ %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' : ' '));
+    AF_DUMP(( "\n" ));
   }
 #ifdef __cplusplus
   }
@@ -247,7 +259,8 @@
   extern "C" {
 #endif
   void
-  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
+  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
+                                FT_Bool        to_stdout )
   {
     FT_Int  dimension;
 
@@ -262,34 +275,34 @@
       AF_Segment    seg;
 
 
-      FT_TRACE7(( "Table of %s segments:\n",
-                  dimension == AF_DIMENSION_HORZ ? "vertical"
-                                                 : "horizontal" ));
+      AF_DUMP(( "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" ));
+        AF_DUMP(( "  [ index |  pos  |  dir  | from"
+                  " |  to  | link | serif | edge"
+                  " | height | extra |    flags    ]\n" ));
       else
-        FT_TRACE7(( "  (none)\n" ));
+        AF_DUMP(( "  (none)\n" ));
 
       for ( seg = segments; seg < limit; seg++ )
-        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" ));
+        AF_DUMP(( "  [ %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 ) ));
+      AF_DUMP(( "\n" ));
     }
   }
 #ifdef __cplusplus
@@ -366,7 +379,8 @@
   extern "C" {
 #endif
   void
-  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
+  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
+                             FT_Bool        to_stdout )
   {
     FT_Int  dimension;
 
@@ -383,94 +397,35 @@
        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
        *        since they have a constant X coordinate.
        */
-      FT_TRACE7(( "Table of %s edges:\n",
-                  dimension == AF_DIMENSION_HORZ ? "vertical"
-                                                 : "horizontal" ));
+      AF_DUMP(( "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" ));
+        AF_DUMP(( "  [ index |  pos  |  dir  | link"
+                  " | serif | blue | opos  |  pos  |    flags    ]\n" ));
       else
-        FT_TRACE7(( "  (none)\n" ));
+        AF_DUMP(( "  (none)\n" ));
 
       for ( edge = edges; edge < limit; edge++ )
-        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" ));
+        AF_DUMP(( "  [ %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 ) ));
+      AF_DUMP(( "\n" ));
     }
   }
 #ifdef __cplusplus
   }
 #endif
 
-#else /* !FT_DEBUG_AUTOFIT */
-
-  /* these empty stubs are only used to link the `ftgrid' test program */
-  /* if debugging is disabled                                          */
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-  void
-  af_glyph_hints_dump_points( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-
-  void
-  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-
-  FT_Error
-  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
-                                   FT_Int         dimension,
-                                   FT_Int*        num_segments )
-  {
-    FT_UNUSED( hints );
-    FT_UNUSED( dimension );
-    FT_UNUSED( num_segments );
-
-    return 0;
-  }
-
-
-  FT_Error
-  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
-                                     FT_Int         dimension,
-                                     FT_Int         idx,
-                                     FT_Pos*        offset )
-  {
-    FT_UNUSED( hints );
-    FT_UNUSED( dimension );
-    FT_UNUSED( idx );
-    FT_UNUSED( offset );
-
-    return 0;
-  }
-
-
-  void
-  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-#ifdef __cplusplus
-  }
-#endif
+#undef AF_DUMP
 
 #endif /* !FT_DEBUG_AUTOFIT */
 
@@ -740,6 +695,12 @@
         FT_Pos        in_y   = 0;
         AF_Direction  in_dir = AF_DIR_NONE;
 
+        FT_Pos  last_good_in_x = 0;
+        FT_Pos  last_good_in_y = 0;
+
+        FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
+        FT_Int   near_limit   = 20 * units_per_em / 2048;
+
 
         for ( point = points; point < point_limit; point++ )
         {
@@ -749,15 +710,59 @@
 
           if ( point == first )
           {
-            prev   = first->prev;
-            in_x   = first->fx - prev->fx;
-            in_y   = first->fy - prev->fy;
+            prev = first->prev;
+
+            in_x = first->fx - prev->fx;
+            in_y = first->fy - prev->fy;
+
+            last_good_in_x = in_x;
+            last_good_in_y = in_y;
+
+            if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit )
+            {
+              /* search first non-near point to get a good `in_dir' value */
+
+              AF_Point  point_ = prev;
+
+
+              while ( point_ != first )
+              {
+                AF_Point  prev_ = point_->prev;
+
+                FT_Pos  in_x_ = point_->fx - prev_->fx;
+                FT_Pos  in_y_ = point_->fy - prev_->fy;
+
+
+                if ( FT_ABS( in_x_ ) + FT_ABS( in_y_ ) >= near_limit )
+                {
+                  last_good_in_x = in_x_;
+                  last_good_in_y = in_y_;
+
+                  break;
+                }
+
+                point_ = prev_;
+              }
+            }
+
             in_dir = af_direction_compute( in_x, in_y );
             first  = prev + 1;
           }
 
           point->in_dir = (FT_Char)in_dir;
 
+          /* check whether the current point is near to the previous one */
+          /* (value 20 in `near_limit' is heuristic; we use Taxicab      */
+          /* metrics for the test)                                       */
+
+          if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit )
+            point->flags |= AF_FLAG_NEAR;
+          else
+          {
+            last_good_in_x = in_x;
+            last_good_in_y = in_y;
+          }
+
           next  = point->next;
           out_x = next->fx - point->fx;
           out_y = next->fy - point->fy;
@@ -765,23 +770,43 @@
           in_dir         = af_direction_compute( out_x, out_y );
           point->out_dir = (FT_Char)in_dir;
 
-          /* check for weak points */
+          /* Check for weak points.  The remaining points not collected */
+          /* in edges are then implicitly classified as strong points.  */
 
           if ( point->flags & AF_FLAG_CONTROL )
           {
+            /* control points are always weak */
           Is_Weak_Point:
             point->flags |= AF_FLAG_WEAK_INTERPOLATION;
           }
           else if ( point->out_dir == point->in_dir )
           {
             if ( point->out_dir != AF_DIR_NONE )
+            {
+              /* current point lies on a horizontal or          */
+              /* vertical segment (but doesn't start or end it) */
               goto Is_Weak_Point;
+            }
 
-            if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
+            /* test whether `in' and `out' direction is approximately */
+            /* the same (and use the last good `in' vector in case    */
+            /* the current point is near to the previous one)         */
+            if ( ft_corner_is_flat(
+                   point->flags & AF_FLAG_NEAR ? last_good_in_x : in_x,
+                   point->flags & AF_FLAG_NEAR ? last_good_in_y : in_y,
+                   out_x,
+                   out_y ) )
+            {
+              /* current point lies on a straight, diagonal line */
+              /* (more or less)                                  */
               goto Is_Weak_Point;
+            }
           }
           else if ( point->in_dir == -point->out_dir )
+          {
+            /* current point forms a spike */
             goto Is_Weak_Point;
+          }
 
           in_x = out_x;
           in_y = out_y;
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 776b3c8..ce52325 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -62,15 +62,19 @@
    *
    *  by David Turner and Werner Lemberg
    *
-   *   http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+   *    http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+   *
+   *  with appropriate updates.
    *
    *
    *  Segments
    *
    *    `af_{cjk,latin,...}_hints_compute_segments' are the functions to
-   *    find segments in an outline.  A segment is a series of consecutive
-   *    points that are approximately aligned along a coordinate axis.  The
-   *    analysis to do so is specific to a script.
+   *    find segments in an outline.
+   *
+   *    A segment is a series of consecutive points that are approximately
+   *    aligned along a coordinate axis.  The analysis to do so is specific
+   *    to a writing system.
    *
    *    A segment must have at least two points, except in the case of
    *    `fake' segments that are generated to hint metrics appropriately,
@@ -79,16 +83,17 @@
    *
    *  Edges
    *
+   *    `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
+   *    edges.
+   *
    *    As soon as segments are defined, the auto-hinter groups them into
    *    edges.  An edge corresponds to a single position on the main
    *    dimension that collects one or more segments (allowing for a small
    *    threshold).
    *
-   *    The auto-hinter first tries to grid fit edges, then to align
-   *    segments on the edges unless it detects that they form a serif.
-   *
-   *    `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
-   *    edges; they are specific to a script.
+   *    As an example, the `latin' writing system first tries to grid-fit
+   *    edges, then to align segments on the edges unless it detects that
+   *    they form a serif.
    *
    *
    *                      A          H
@@ -107,6 +112,8 @@
    *
    *  Stems
    *
+   *    Stems are detected by `af_{cjk,latin,...}_hint_edges'.
+   *
    *    Segments need to be `linked' to other ones in order to detect stems.
    *    A stem is made of two segments that face each other in opposite
    *    directions and that are sufficiently close to each other.  Using
@@ -127,17 +134,21 @@
    *    The best candidate is stored in field `link' in structure
    *    `AF_Segment'.
    *
-   *    Stems are detected by `af_{cjk,latin,...}_hint_edges'.
-   *
    *    In the above ASCII drawing, the best candidate for both AB and CD is
    *    GH, while the best candidate for GH is AB.  Similarly, the best
    *    candidate for EF and GH is AB, while the best candidate for AB is
    *    GH.
    *
+   *    The detection and handling of stems is dependent on the writing
+   *    system.
+   *
    *
    *  Serifs
    *
-   *    On the opposite, a serif has
+   *    Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+   *
+   *    In comparison to a stem, a serif (as handled by the auto-hinter
+   *    module which takes care of the `latin' writing system) has
    *
    *      best segment_1 = segment_2 && best segment_2 != segment_1
    *
@@ -147,8 +158,6 @@
    *    The best candidate is stored in field `serif' in structure
    *    `AF_Segment' (and `link' is set to NULL).
    *
-   *    Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
-   *
    *
    *  Touched points
    *
@@ -178,7 +187,8 @@
    *      differ greatly)
    *
    *    - inflection points (i.e., where the `in' and `out' angles are the
-   *      same, but the curvature changes sign)
+   *      same, but the curvature changes sign) [currently, such points
+   *      aren't handled in the auto-hinter]
    *
    *    `af_glyph_hints_align_strong_points' is the function which takes
    *    care of such situations; it is equivalent to the TrueType `IP'
@@ -226,7 +236,10 @@
     AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
 
     /* all inflection points in the outline have this flag set */
-    AF_FLAG_INFLECTION = 1 << 9
+    AF_FLAG_INFLECTION = 1 << 9,
+
+    /* the current point is very near to another one */
+    AF_FLAG_NEAR = 1 << 10
 
   } AF_Flags;
 
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 8c24972..ef8299f 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -97,26 +97,10 @@
   /*************************************************************************/
 
 
-  static const AF_Script_UniRangeRec  af_indic_uniranges[] =
-  {
-#if 0
-    AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ),  /* why this? */
-#endif
-    AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL),    /* Indic Range */
-    AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL),    /* Tibetan */
-    AF_UNIRANGE_REC( 0x1900UL, 0x194FUL),    /* Limbu */
-    AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL),    /* Sundanese */
-    AF_UNIRANGE_REC( 0x1C80UL, 0x1CDFUL),    /* Meetei Mayak */
-    AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL),    /* Syloti Nagri */
-    AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL),  /* Sharada */
-    AF_UNIRANGE_REC(      0UL,      0UL)
-  };
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_indic_writing_system_class,
 
-
-  AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
-    AF_SCRIPT_INDIC,
-    af_indic_uniranges,
-    'o', /* XXX */
+    AF_WRITING_SYSTEM_INDIC,
 
     sizeof ( AF_CJKMetricsRec ),
 
@@ -128,18 +112,28 @@
     (AF_Script_ApplyHintsFunc)  af_indic_hints_apply
   )
 
-#else /* !AF_CONFIG_OPTION_INDIC */
+  /* XXX: this should probably fine tuned to differentiate better between */
+  /*      scripts...                                                      */
 
-  static const AF_Script_UniRangeRec  af_indic_uniranges[] =
+  static const AF_Script_UniRangeRec  af_deva_uniranges[] =
   {
-    { 0, 0 }
+    AF_UNIRANGE_REC(  0x0900UL,  0x0DFFUL ),  /* Indic Range  */
+    AF_UNIRANGE_REC(  0x0F00UL,  0x0FFFUL ),  /* Tibetan      */
+    AF_UNIRANGE_REC(  0x1900UL,  0x194FUL ),  /* Limbu        */
+    AF_UNIRANGE_REC(  0x1B80UL,  0x1BBFUL ),  /* Sundanese    */
+    AF_UNIRANGE_REC(  0x1C80UL,  0x1CDFUL ),  /* Meetei Mayak */
+    AF_UNIRANGE_REC(  0xA800UL,  0xA82FUL ),  /* Syloti Nagri */
+    AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL ),  /* Sharada      */
+    AF_UNIRANGE_REC(       0UL,       0UL )
   };
 
 
-  AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
-    AF_SCRIPT_INDIC,
-    af_indic_uniranges,
-    0,
+#else /* !AF_CONFIG_OPTION_INDIC */
+
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_indic_writing_system_class,
+
+    AF_WRITING_SYSTEM_INDIC,
 
     sizeof ( AF_CJKMetricsRec ),
 
@@ -151,7 +145,25 @@
     (AF_Script_ApplyHintsFunc)  NULL
   )
 
+
+  static const AF_Script_UniRangeRec  af_deva_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0UL, 0UL )
+  };
+
 #endif /* !AF_CONFIG_OPTION_INDIC */
 
 
+  AF_DEFINE_SCRIPT_CLASS(
+    af_deva_script_class,
+
+    AF_SCRIPT_DEVA,
+    (AF_Blue_Stringset)0, /* XXX */
+    AF_WRITING_SYSTEM_INDIC,
+
+    af_deva_uniranges,
+    'o' /* XXX */
+  )
+
+
 /* END */
diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h
index c252cf2..db38e96 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, 2012 by                                                */
+/*  Copyright 2007, 2012, 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,       */
@@ -25,9 +25,14 @@
 FT_BEGIN_HEADER
 
 
-  /* the Indic-specific script class */
+  /* the `indic' writing system */
 
-  AF_DECLARE_SCRIPT_CLASS( af_indic_script_class )
+  AF_DECLARE_WRITING_SYSTEM_CLASS( af_indic_writing_system_class )
+
+
+  /* the indic-specific script classes */
+
+  AF_DECLARE_SCRIPT_CLASS( af_deva_script_class )
 
 
 /* */
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index ef0157a..15a241e 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -60,8 +60,11 @@
     AF_GlyphHintsRec  hints[1];
 
 
-    FT_TRACE5(( "standard widths computation\n"
-                "===========================\n\n" ));
+    FT_TRACE5(( "\n"
+                "latin standard widths computation (script `%s')\n"
+                "=================================================\n"
+                "\n",
+                af_script_names[metrics->root.script_class->script] ));
 
     af_glyph_hints_init( hints, face->memory );
 
@@ -76,13 +79,14 @@
       AF_Scaler           scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face,
-                                       metrics->root.clazz->standard_char );
+      glyph_index = FT_Get_Char_Index(
+                      face,
+                      metrics->root.script_class->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 ));
+      FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
+                  metrics->root.script_class->standard_char, glyph_index ));
 
       error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
       if ( error || face->glyph->outline.n_points <= 0 )
@@ -146,22 +150,21 @@
         }
 
         /* this also replaces multiple almost identical stem widths */
-        /* with a single one (the value 100 is heuristic) */
+        /* 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;
       }
 
-  Exit:
+    Exit:
       for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
       {
         AF_LatinAxis  axis = &metrics->axis[dim];
         FT_Pos        stdw;
 
 
-        stdw = ( axis->width_count > 0 )
-                 ? axis->widths[0].org
-                 : AF_LATIN_CONSTANT( metrics, 50 );
+        stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
+                                         : AF_LATIN_CONSTANT( metrics, 50 );
 
         /* let's try 20% of the smallest width */
         axis->edge_distance_threshold = stdw / 5;
@@ -193,22 +196,6 @@
   }
 
 
-
-#define AF_LATIN_MAX_TEST_CHARACTERS  12
-
-
-  static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES]
-                                       [AF_LATIN_MAX_TEST_CHARACTERS + 1] =
-  {
-    "THEZOCQS",
-    "HEZLOCUS",
-    "fijkdbh",
-    "xzroesc",
-    "xzroesc",
-    "pqgjy"
-  };
-
-
   /* Find all blue zones.  Flat segments give the reference points, */
   /* round segments the overshoot positions.                        */
 
@@ -216,39 +203,80 @@
   af_latin_metrics_init_blues( AF_LatinMetrics  metrics,
                                FT_Face          face )
   {
-    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
-    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
+    FT_Pos        flats [AF_BLUE_STRING_MAX_LEN];
+    FT_Pos        rounds[AF_BLUE_STRING_MAX_LEN];
+
     FT_Int        num_flats;
     FT_Int        num_rounds;
-    FT_Int        bb;
+
     AF_LatinBlue  blue;
     FT_Error      error;
-    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
+    AF_LatinAxis  axis = &metrics->axis[AF_DIMENSION_VERT];
     FT_Outline    outline;
 
+    AF_Blue_Stringset         bss = metrics->root.script_class->blue_stringset;
+    const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
 
-    /* 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"
-                "======================\n\n" ));
+    /* we walk over the blue character strings as specified in the  */
+    /* script's entry in the `af_blue_stringset' array              */
 
-    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+    FT_TRACE5(( "latin blue zones computation\n"
+                "============================\n"
+                "\n" ));
+
+    for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
-      const char*  p     = af_latin_blue_chars[bb];
-      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
+      const char*  p = &af_blue_strings[bs->string];
       FT_Pos*      blue_ref;
       FT_Pos*      blue_shoot;
 
 
-      FT_TRACE5(( "blue zone %d:\n", bb ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+      {
+        FT_Bool  have_flag = 0;
+
+
+        FT_TRACE5(( "blue zone %d", axis->blue_count ));
+
+        if ( bs->properties )
+        {
+          FT_TRACE5(( " (" ));
+
+          if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+          {
+            FT_TRACE5(( "top" ));
+            have_flag = 1;
+          }
+
+          if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
+          {
+            if ( have_flag )
+              FT_TRACE5(( ", " ));
+            FT_TRACE5(( "small top" ));
+            have_flag = 1;
+          }
+
+          if ( AF_LATIN_IS_LONG_BLUE( bs ) )
+          {
+            if ( have_flag )
+              FT_TRACE5(( ", " ));
+            FT_TRACE5(( "long" ));
+          }
+
+          FT_TRACE5(( ")" ));
+        }
+
+        FT_TRACE5(( ":\n" ));
+      }
+#endif /* FT_DEBUG_LEVEL_TRACE */
 
       num_flats  = 0;
       num_rounds = 0;
 
-      for ( ; p < limit && *p; p++ )
+      while ( *p )
       {
+        FT_ULong    ch;
         FT_UInt     glyph_index;
         FT_Pos      best_y;                            /* same as points.y */
         FT_Int      best_point, best_contour_first, best_contour_last;
@@ -256,15 +284,23 @@
         FT_Bool     round = 0;
 
 
+        GET_UTF8_CHAR( ch, p );
+
         /* load the character in the face -- skip unknown or empty ones */
-        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+        glyph_index = FT_Get_Char_Index( face, ch );
         if ( glyph_index == 0 )
+        {
+          FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
           continue;
+        }
 
         error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
         outline = face->glyph->outline;
         if ( error || outline.n_points <= 0 )
+        {
+          FT_TRACE5(( "  U+%04lX contains no outlines\n", ch ));
           continue;
+        }
 
         /* now compute min or max point indices and coordinates */
         points             = outline.points;
@@ -289,11 +325,11 @@
 
             /* Avoid single-point contours since they are never rasterized. */
             /* In some fonts, they correspond to mark attachment points     */
-            /* which are way outside of the glyph's real outline.           */
+            /* that are way outside of the glyph's real outline.            */
             if ( last <= first )
               continue;
 
-            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+            if ( AF_LATIN_IS_TOP_BLUE( bs ) )
             {
               for ( pp = first; pp <= last; pp++ )
                 if ( best_point < 0 || points[pp].y > best_y )
@@ -318,7 +354,6 @@
               best_contour_last  = last;
             }
           }
-          FT_TRACE5(( "  %c  %ld", *p, best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
@@ -328,10 +363,14 @@
         {
           FT_Pos  best_x = points[best_point].x;
           FT_Int  prev, next;
+          FT_Int  best_segment_first, best_segment_last;
           FT_Int  best_on_point_first, best_on_point_last;
           FT_Pos  dist;
 
 
+          best_segment_first = best_point;
+          best_segment_last  = best_point;
+
           if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
           {
             best_on_point_first = best_point;
@@ -343,8 +382,9 @@
             best_on_point_last  = -1;
           }
 
-          /* look for the previous and next points that are not on the */
-          /* same Y coordinate, then threshold the `closeness'...      */
+          /* look for the previous and next points on the contour  */
+          /* that are not on the same Y coordinate, then threshold */
+          /* the `closeness'...                                    */
           prev = best_point;
           next = prev;
 
@@ -362,6 +402,8 @@
               if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
                 break;
 
+            best_segment_first = prev;
+
             if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
             {
               best_on_point_first = prev;
@@ -383,6 +425,8 @@
               if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
                 break;
 
+            best_segment_last = next;
+
             if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
             {
               best_on_point_last = next;
@@ -392,8 +436,186 @@
 
           } while ( next != best_point );
 
-          /* now set the `round' flag depending on the segment's kind */
-          /* (value 8 is heuristic)                                   */
+          if ( AF_LATIN_IS_LONG_BLUE( bs ) )
+          {
+            /* If this flag is set, we have an additional constraint to  */
+            /* get the blue zone distance: Find a segment of the topmost */
+            /* (or bottommost) contour that is longer than a heuristic   */
+            /* threshold.  This ensures that small bumps in the outline  */
+            /* are ignored (for example, the `vertical serifs' found in  */
+            /* many Hebrew glyph designs).                               */
+
+            /* If this segment is long enough, we are done.  Otherwise,  */
+            /* search the segment next to the extremum that is long      */
+            /* enough, has the same direction, and a not too large       */
+            /* vertical distance from the extremum.  Note that the       */
+            /* algorithm doesn't check whether the found segment is      */
+            /* actually the one (vertically) nearest to the extremum.    */
+
+            /* heuristic threshold value */
+            FT_Pos  length_threshold = metrics->units_per_em / 25;
+
+
+            dist = FT_ABS( points[best_segment_last].x -
+                             points[best_segment_first].x );
+
+            if ( dist < length_threshold                       &&
+                 best_segment_last - best_segment_first + 2 <=
+                   best_contour_last - best_contour_first      )
+            {
+              /* heuristic threshold value */
+              FT_Pos  height_threshold = metrics->units_per_em / 4;
+
+              FT_Int   first;
+              FT_Int   last;
+              FT_Bool  hit;
+
+              FT_Bool  left2right;
+
+
+              /* compute direction */
+              prev = best_point;
+
+              do
+              {
+                if ( prev > best_contour_first )
+                  prev--;
+                else
+                  prev = best_contour_last;
+
+                if ( points[prev].x != best_x )
+                  break;
+
+              } while ( prev != best_point );
+
+              /* skip glyph for the degenerate case */
+              if ( prev == best_point )
+                continue;
+
+              left2right = FT_BOOL( points[prev].x < points[best_point].x );
+
+              first = best_segment_last;
+              last  = first;
+              hit   = 0;
+
+              do
+              {
+                FT_Bool  l2r;
+                FT_Pos   d;
+                FT_Int   p_first, p_last;
+
+
+                if ( !hit )
+                {
+                  /* no hit; adjust first point */
+                  first = last;
+
+                  /* also adjust first and last on point */
+                  if ( FT_CURVE_TAG( outline.tags[first] ) ==
+                         FT_CURVE_TAG_ON )
+                  {
+                    p_first = first;
+                    p_last  = first;
+                  }
+                  else
+                  {
+                    p_first = -1;
+                    p_last  = -1;
+                  }
+
+                  hit = 1;
+                }
+
+                if ( last < best_contour_last )
+                  last++;
+                else
+                  last = best_contour_first;
+
+                if ( FT_ABS( best_y - points[first].y ) > height_threshold )
+                {
+                  /* vertical distance too large */
+                  hit = 0;
+                  continue;
+                }
+
+                /* same test as above */
+                dist = FT_ABS( points[last].y - points[first].y );
+                if ( dist > 5 )
+                  if ( FT_ABS( points[last].x - points[first].x ) <=
+                         20 * dist )
+                  {
+                    hit = 0;
+                    continue;
+                  }
+
+                if ( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
+                {
+                  p_last = last;
+                  if ( p_first < 0 )
+                    p_first = last;
+                }
+
+                l2r = FT_BOOL( points[first].x < points[last].x );
+                d   = FT_ABS( points[last].x - points[first].x );
+
+                if ( l2r == left2right     &&
+                     d >= length_threshold )
+                {
+                  /* all constraints are met; update segment after finding */
+                  /* its end                                               */
+                  do
+                  {
+                    if ( last < best_contour_last )
+                      last++;
+                    else
+                      last = best_contour_first;
+
+                    d = FT_ABS( points[last].y - points[first].y );
+                    if ( d > 5 )
+                      if ( FT_ABS( points[next].x - points[first].x ) <=
+                             20 * dist )
+                      {
+                        last--;
+                        break;
+                      }
+
+                    p_last = last;
+
+                    if ( FT_CURVE_TAG( outline.tags[last] ) ==
+                           FT_CURVE_TAG_ON )
+                    {
+                      p_last = last;
+                      if ( p_first < 0 )
+                        p_first = last;
+                    }
+
+                  } while ( last != best_segment_first );
+
+                  best_y = points[first].y;
+
+                  best_segment_first = first;
+                  best_segment_last  = last;
+
+                  best_on_point_first = p_first;
+                  best_on_point_last  = p_last;
+
+                  break;
+                }
+
+              } while ( last != best_segment_first );
+            }
+          }
+
+          FT_TRACE5(( "  U+%04lX: best_y = %5ld", ch, best_y ));
+
+          /* now set the `round' flag depending on the segment's kind: */
+          /*                                                           */
+          /* - if the horizontal distance between the first and last   */
+          /*   `on' point is larger than upem/8 (value 8 is heuristic) */
+          /*   we have a flat segment                                  */
+          /* - if either the first or the last point of the segment is */
+          /*   an `off' point, the segment is round, otherwise it is   */
+          /*   flat                                                    */
           if ( best_on_point_first >= 0                               &&
                best_on_point_last >= 0                                &&
                (FT_UInt)( FT_ABS( points[best_on_point_last].x -
@@ -402,8 +624,10 @@
             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_CURVE_TAG( outline.tags[best_segment_first] ) !=
+                        FT_CURVE_TAG_ON                                   ||
+                      FT_CURVE_TAG( outline.tags[best_segment_last]  ) !=
+                        FT_CURVE_TAG_ON                                   );
 
           FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
         }
@@ -448,7 +672,7 @@
       }
       else
       {
-        *blue_ref   = flats[num_flats / 2];
+        *blue_ref   = flats [num_flats  / 2];
         *blue_shoot = rounds[num_rounds / 2];
       }
 
@@ -462,7 +686,7 @@
         FT_Bool  over_ref = FT_BOOL( shoot > ref );
 
 
-        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+        if ( AF_LATIN_IS_TOP_BLUE( bs ) ^ over_ref )
         {
           *blue_ref   =
           *blue_shoot = ( shoot + ref ) / 2;
@@ -473,7 +697,7 @@
       }
 
       blue->flags = 0;
-      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+      if ( AF_LATIN_IS_TOP_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_TOP;
 
       /*
@@ -481,7 +705,7 @@
        * in order to optimize the pixel grid alignment of the top of small
        * letters.
        */
-      if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+      if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
       FT_TRACE5(( "    -> reference = %ld\n"
@@ -650,7 +874,20 @@
           else
 #endif
           if ( dim == AF_DIMENSION_VERT )
+          {
             scale = FT_MulDiv( scale, fitted, scaled );
+
+            FT_TRACE5((
+              "af_latin_metrics_scale_dim:"
+              " x height alignment (script `%s'):\n"
+              "                           "
+              " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
+              "\n",
+              af_script_names[metrics->root.script_class->script],
+              axis->org_scale / 65536.0,
+              scale / 65536.0,
+              ( fitted - scaled ) * 100 / scaled ));
+          }
         }
       }
     }
@@ -669,6 +906,10 @@
       metrics->root.scaler.y_delta = delta;
     }
 
+    FT_TRACE5(( "%s widths (script `%s')\n",
+                dim == AF_DIMENSION_HORZ ? "horizontal" : "vertical",
+                af_script_names[metrics->root.script_class->script] ));
+
     /* scale the widths */
     for ( nn = 0; nn < axis->width_count; nn++ )
     {
@@ -677,15 +918,31 @@
 
       width->cur = FT_MulFix( width->org, scale );
       width->fit = width->cur;
+
+      FT_TRACE5(( "  %d scaled to %.2f\n",
+                  width->org,
+                  width->cur / 64.0 ));
     }
 
+    FT_TRACE5(( "\n" ));
+
     /* an extra-light axis corresponds to a standard width that is */
     /* smaller than 5/8 pixels                                     */
     axis->extra_light =
       (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( axis->extra_light )
+      FT_TRACE5(( "`%s' script is extra light (at current resolution)\n"
+                  "\n",
+                  af_script_names[metrics->root.script_class->script] ));
+#endif
+
     if ( dim == AF_DIMENSION_VERT )
     {
+      FT_TRACE5(( "blue zones (script `%s')\n",
+                  af_script_names[metrics->root.script_class->script] ));
+
       /* scale the blue zones */
       for ( nn = 0; nn < axis->blue_count; nn++ )
       {
@@ -757,6 +1014,19 @@
 #endif
 
           blue->flags |= AF_LATIN_BLUE_ACTIVE;
+
+          FT_TRACE5(( "  reference %d: %d scaled to %.2f%s\n"
+                      "  overshoot %d: %d scaled to %.2f%s\n",
+                      nn,
+                      blue->ref.org,
+                      blue->ref.fit / 64.0,
+                      blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+                                                         : " (inactive)",
+                      nn,
+                      blue->shoot.org,
+                      blue->shoot.fit / 64.0,
+                      blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+                                                         : " (inactive)" ));
         }
       }
     }
@@ -1654,8 +1924,8 @@
                                AF_Edge_Flags  base_flags,
                                AF_Edge_Flags  stem_flags )
   {
-    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
-    AF_LatinAxis     axis     = & metrics->axis[dim];
+    AF_LatinMetrics  metrics  = (AF_LatinMetrics)hints->metrics;
+    AF_LatinAxis     axis     = &metrics->axis[dim];
     FT_Pos           dist     = width;
     FT_Int           sign     = 0;
     FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
@@ -1878,8 +2148,9 @@
 #endif
 
 
-    FT_TRACE5(( "%s edge hinting\n",
-                dim == AF_DIMENSION_VERT ? "horizontal" : "vertical" ));
+    FT_TRACE5(( "latin %s edge hinting (script `%s')\n",
+                dim == AF_DIMENSION_VERT ? "horizontal" : "vertical",
+                af_script_names[hints->metrics->script_class->script] ));
 
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
@@ -2414,6 +2685,7 @@
         af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
       }
     }
+
     af_glyph_hints_save( hints, outline );
 
   Exit:
@@ -2430,47 +2702,10 @@
   /*************************************************************************/
 
 
-  /* XXX: this should probably fine tuned to differentiate better between */
-  /*      scripts...                                                      */
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_latin_writing_system_class,
 
-  static const AF_Script_UniRangeRec  af_latin_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0020UL,  0x007FUL ),  /* Basic Latin (no control chars) */
-    AF_UNIRANGE_REC(  0x00A0UL,  0x00FFUL ),  /* Latin-1 Supplement (no control chars) */
-    AF_UNIRANGE_REC(  0x0100UL,  0x017FUL ),  /* Latin Extended-A */
-    AF_UNIRANGE_REC(  0x0180UL,  0x024FUL ),  /* Latin Extended-B */
-    AF_UNIRANGE_REC(  0x0250UL,  0x02AFUL ),  /* IPA Extensions */
-    AF_UNIRANGE_REC(  0x02B0UL,  0x02FFUL ),  /* Spacing Modifier Letters */
-    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),  /* Combining Diacritical Marks */
-    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
-    AF_UNIRANGE_REC(  0x0400UL,  0x04FFUL ),  /* Cyrillic */
-    AF_UNIRANGE_REC(  0x0500UL,  0x052FUL ),  /* Cyrillic Supplement */
-    AF_UNIRANGE_REC(  0x1D00UL,  0x1D7FUL ),  /* Phonetic Extensions */
-    AF_UNIRANGE_REC(  0x1D80UL,  0x1DBFUL ),  /* Phonetic Extensions Supplement */
-    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),  /* Combining Diacritical Marks Supplement */
-    AF_UNIRANGE_REC(  0x1E00UL,  0x1EFFUL ),  /* Latin Extended Additional */
-    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended */
-    AF_UNIRANGE_REC(  0x2000UL,  0x206FUL ),  /* General Punctuation */
-    AF_UNIRANGE_REC(  0x2070UL,  0x209FUL ),  /* Superscripts and Subscripts */
-    AF_UNIRANGE_REC(  0x20A0UL,  0x20CFUL ),  /* Currency Symbols */
-    AF_UNIRANGE_REC(  0x2150UL,  0x218FUL ),  /* Number Forms */
-    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 )
-  };
-
-
-  AF_DEFINE_SCRIPT_CLASS( af_latin_script_class,
-    AF_SCRIPT_LATIN,
-    af_latin_uniranges,
-    'o',
+    AF_WRITING_SYSTEM_LATIN,
 
     sizeof ( AF_LatinMetricsRec ),
 
@@ -2483,4 +2718,103 @@
   )
 
 
+  /* XXX: this should probably fine tuned to differentiate better between */
+  /*      scripts...                                                      */
+
+  static const AF_Script_UniRangeRec  af_latn_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0020UL,  0x007FUL ),  /* Basic Latin (no control chars) */
+    AF_UNIRANGE_REC(  0x00A0UL,  0x00FFUL ),  /* Latin-1 Supplement (no control chars) */
+    AF_UNIRANGE_REC(  0x0100UL,  0x017FUL ),  /* Latin Extended-A */
+    AF_UNIRANGE_REC(  0x0180UL,  0x024FUL ),  /* Latin Extended-B */
+    AF_UNIRANGE_REC(  0x0250UL,  0x02AFUL ),  /* IPA Extensions */
+    AF_UNIRANGE_REC(  0x02B0UL,  0x02FFUL ),  /* Spacing Modifier Letters */
+    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),  /* Combining Diacritical Marks */
+    AF_UNIRANGE_REC(  0x1D00UL,  0x1D7FUL ),  /* Phonetic Extensions */
+    AF_UNIRANGE_REC(  0x1D80UL,  0x1DBFUL ),  /* Phonetic Extensions Supplement */
+    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),  /* Combining Diacritical Marks Supplement */
+    AF_UNIRANGE_REC(  0x1E00UL,  0x1EFFUL ),  /* Latin Extended Additional */
+    AF_UNIRANGE_REC(  0x2000UL,  0x206FUL ),  /* General Punctuation */
+    AF_UNIRANGE_REC(  0x2070UL,  0x209FUL ),  /* Superscripts and Subscripts */
+    AF_UNIRANGE_REC(  0x20A0UL,  0x20CFUL ),  /* Currency Symbols */
+    AF_UNIRANGE_REC(  0x2150UL,  0x218FUL ),  /* Number Forms */
+    AF_UNIRANGE_REC(  0x2460UL,  0x24FFUL ),  /* Enclosed Alphanumerics */
+    AF_UNIRANGE_REC(  0x2C60UL,  0x2C7FUL ),  /* Latin Extended-C */
+    AF_UNIRANGE_REC(  0x2E00UL,  0x2E7FUL ),  /* Supplemental Punctuation */
+    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 )
+  };
+
+  static const AF_Script_UniRangeRec  af_grek_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
+    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended */
+    AF_UNIRANGE_REC(       0UL,       0UL )
+  };
+
+  static const AF_Script_UniRangeRec  af_cyrl_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0400UL,  0x04FFUL ),  /* Cyrillic */
+    AF_UNIRANGE_REC(  0x0500UL,  0x052FUL ),  /* Cyrillic Supplement */
+    AF_UNIRANGE_REC(  0x2DE0UL,  0x2DFFUL ),  /* Cyrillic Extended-A */
+    AF_UNIRANGE_REC(  0xA640UL,  0xA69FUL ),  /* Cyrillic Extended-B */
+    AF_UNIRANGE_REC(       0UL,       0UL )
+  };
+
+  static const AF_Script_UniRangeRec  af_hebr_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0590UL,  0x05FFUL ),  /* Hebrew */
+    AF_UNIRANGE_REC(  0xFB1DUL,  0xFB4FUL ),  /* Alphab. Present. Forms (Hebrew) */
+    AF_UNIRANGE_REC(       0UL,       0UL )
+  };
+
+
+  AF_DEFINE_SCRIPT_CLASS(
+    af_latn_script_class,
+
+    AF_SCRIPT_LATN,
+    AF_BLUE_STRINGSET_LATN,
+    AF_WRITING_SYSTEM_LATIN,
+
+    af_latn_uniranges,
+    'o'
+  )
+
+  AF_DEFINE_SCRIPT_CLASS(
+    af_grek_script_class,
+
+    AF_SCRIPT_GREK,
+    AF_BLUE_STRINGSET_GREK,
+    AF_WRITING_SYSTEM_LATIN,
+
+    af_grek_uniranges,
+    0x3BF /* ο */
+  )
+
+  AF_DEFINE_SCRIPT_CLASS(
+    af_cyrl_script_class,
+
+    AF_SCRIPT_CYRL,
+    AF_BLUE_STRINGSET_CYRL,
+    AF_WRITING_SYSTEM_LATIN,
+
+    af_cyrl_uniranges,
+    0x43E /* о */
+  )
+
+  AF_DEFINE_SCRIPT_CLASS(
+    af_hebr_script_class,
+
+    AF_SCRIPT_HEBR,
+    AF_BLUE_STRINGSET_HEBR,
+    AF_WRITING_SYSTEM_LATIN,
+
+    af_hebr_uniranges,
+    0x5DD /* ם */
+  )
+
+
 /* END */
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index d9170b3..c06cbd9 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-2012 by                                */
+/*  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,       */
@@ -24,10 +24,20 @@
 
 FT_BEGIN_HEADER
 
+  /* the `latin' writing system */
 
-  /* the latin-specific script class */
+  AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin_writing_system_class )
 
-  AF_DECLARE_SCRIPT_CLASS( af_latin_script_class )
+
+  /* the latin-specific script classes */
+
+  AF_DECLARE_SCRIPT_CLASS( af_cyrl_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_grek_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_latn_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_hebr_script_class )
+#if 0
+  AF_DECLARE_SCRIPT_CLASS( af_armn_script_class )
+#endif
 
 
   /* constants are given with units_per_em == 2048 in mind */
@@ -51,27 +61,14 @@
    */
 
 
-  /* Latin (global) metrics management */
-
-  enum
-  {
-    AF_LATIN_BLUE_CAPITAL_TOP,
-    AF_LATIN_BLUE_CAPITAL_BOTTOM,
-    AF_LATIN_BLUE_SMALL_F_TOP,
-    AF_LATIN_BLUE_SMALL_TOP,
-    AF_LATIN_BLUE_SMALL_BOTTOM,
-    AF_LATIN_BLUE_SMALL_MINOR,
-
-    AF_LATIN_BLUE_MAX
-  };
-
-
-#define AF_LATIN_IS_TOP_BLUE( b )  ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
-                                     (b) == AF_LATIN_BLUE_SMALL_F_TOP || \
-                                     (b) == AF_LATIN_BLUE_SMALL_TOP   )
+#define AF_LATIN_IS_TOP_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
+#define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
+#define AF_LATIN_IS_LONG_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )
 
 #define AF_LATIN_MAX_WIDTHS  16
-#define AF_LATIN_MAX_BLUES   AF_LATIN_BLUE_MAX
 
 
   enum
@@ -106,7 +103,7 @@
 
     /* ignored for horizontal metrics */
     FT_UInt          blue_count;
-    AF_LatinBlueRec  blues[AF_LATIN_BLUE_MAX];
+    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX];
 
     FT_Fixed         org_scale;
     FT_Pos           org_delta;
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index b1e9658..a6d564a 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -76,8 +76,9 @@
       AF_Scaler            scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face,
-                                       metrics->root.clazz->standard_char );
+      glyph_index = FT_Get_Char_Index(
+                      face,
+                      metrics->root.script_class->standard_char );
       if ( glyph_index == 0 )
         goto Exit;
 
@@ -409,11 +410,11 @@
         blue->flags |= AF_LATIN_BLUE_TOP;
 
       /*
-       * The following flags is used later to adjust the y and x scales
+       * The following flag is used later to adjust the y and x scales
        * in order to optimize the pixel grid alignment of the top of small
        * letters.
        */
-      if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+      if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
       FT_TRACE5(( "    -> reference = %ld\n"
@@ -2379,18 +2380,10 @@
   /*************************************************************************/
 
 
-  static const AF_Script_UniRangeRec  af_latin2_uniranges[] =
-  {
-    AF_UNIRANGE_REC( 32UL,  127UL ),    /* TODO: Add new Unicode ranges here! */
-    AF_UNIRANGE_REC( 160UL, 255UL ),
-    AF_UNIRANGE_REC( 0UL,   0UL )
-  };
+  AF_DEFINE_WRITING_SYSTEM_CLASS(
+    af_latin2_writing_system_class,
 
-
-  AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class,
-    AF_SCRIPT_LATIN2,
-    af_latin2_uniranges,
-    'o',
+    AF_WRITING_SYSTEM_LATIN2,
 
     sizeof ( AF_LatinMetricsRec ),
 
@@ -2403,4 +2396,53 @@
   )
 
 
+  /* XXX: this should probably fine tuned to differentiate better between */
+  /*      scripts...                                                      */
+
+  static const AF_Script_UniRangeRec  af_ltn2_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0020UL,  0x007FUL ),  /* Basic Latin (no control chars) */
+    AF_UNIRANGE_REC(  0x00A0UL,  0x00FFUL ),  /* Latin-1 Supplement (no control chars) */
+    AF_UNIRANGE_REC(  0x0100UL,  0x017FUL ),  /* Latin Extended-A */
+    AF_UNIRANGE_REC(  0x0180UL,  0x024FUL ),  /* Latin Extended-B */
+    AF_UNIRANGE_REC(  0x0250UL,  0x02AFUL ),  /* IPA Extensions */
+    AF_UNIRANGE_REC(  0x02B0UL,  0x02FFUL ),  /* Spacing Modifier Letters */
+    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),  /* Combining Diacritical Marks */
+    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
+    AF_UNIRANGE_REC(  0x0400UL,  0x04FFUL ),  /* Cyrillic */
+    AF_UNIRANGE_REC(  0x0500UL,  0x052FUL ),  /* Cyrillic Supplement */
+    AF_UNIRANGE_REC(  0x1D00UL,  0x1D7FUL ),  /* Phonetic Extensions */
+    AF_UNIRANGE_REC(  0x1D80UL,  0x1DBFUL ),  /* Phonetic Extensions Supplement */
+    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),  /* Combining Diacritical Marks Supplement */
+    AF_UNIRANGE_REC(  0x1E00UL,  0x1EFFUL ),  /* Latin Extended Additional */
+    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended */
+    AF_UNIRANGE_REC(  0x2000UL,  0x206FUL ),  /* General Punctuation */
+    AF_UNIRANGE_REC(  0x2070UL,  0x209FUL ),  /* Superscripts and Subscripts */
+    AF_UNIRANGE_REC(  0x20A0UL,  0x20CFUL ),  /* Currency Symbols */
+    AF_UNIRANGE_REC(  0x2150UL,  0x218FUL ),  /* Number Forms */
+    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 )
+  };
+
+
+  AF_DEFINE_SCRIPT_CLASS(
+    af_ltn2_script_class,
+
+    AF_SCRIPT_LTN2,
+    AF_BLUE_STRINGSET_LATN,
+    AF_WRITING_SYSTEM_LATIN2,
+
+    af_ltn2_uniranges,
+    'o'
+  )
+
+
 /* END */
diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h
index cbfa395..f7f6d8d 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-2007, 2012 by                                           */
+/*  Copyright 2003-2007, 2012, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,9 +25,21 @@
 FT_BEGIN_HEADER
 
 
-  /* the latin-specific script class */
+  /* the `latin' writing system */
 
-  AF_DECLARE_SCRIPT_CLASS( af_latin2_script_class )
+  AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
+
+
+  /* the latin-specific script classes */
+
+  AF_DECLARE_SCRIPT_CLASS( af_ltn2_script_class )  /* XXX */
+#if 0
+  AF_DECLARE_SCRIPT_CLASS( af_arm2_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_cyr2_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_grk2_script_class )
+  AF_DECLARE_SCRIPT_CLASS( af_hbr2_script_class )
+#endif
+
 
 /* */
 
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 17a6fb7..400b01e 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -21,6 +21,7 @@
 #include "afhints.h"
 #include "aferrors.h"
 #include "afmodule.h"
+#include "afpic.h"
 
 
   /* Initialize glyph loader. */
@@ -180,10 +181,20 @@
 
       /* now load the slot image into the auto-outline and run the */
       /* automatic hinting process                                 */
-      if ( metrics->clazz->script_hints_apply )
-        metrics->clazz->script_hints_apply( hints,
-                                            &gloader->current.outline,
-                                            metrics );
+      {
+#ifdef FT_CONFIG_OPTION_PIC
+        AF_FaceGlobals         globals              = loader->globals;
+#endif
+        AF_WritingSystemClass  writing_system_class =
+                                 AF_WRITING_SYSTEM_CLASSES_GET
+                                   [metrics->script_class->writing_system];
+
+
+        if ( writing_system_class->script_hints_apply )
+          writing_system_class->script_hints_apply( hints,
+                                                    &gloader->current.outline,
+                                                    metrics );
+      }
 
       /* we now need to adjust the metrics according to the change in */
       /* width/positioning that occurred during the hinting process   */
@@ -519,33 +530,41 @@
     if ( !error )
     {
       AF_ScriptMetrics  metrics;
-      FT_UInt           options = 0;
+      FT_UInt           options = AF_SCRIPT_NONE;
 
 
 #ifdef FT_OPTION_AUTOFIT2
-      /* XXX: undocumented hook to activate the latin2 hinter */
+      /* XXX: undocumented hook to activate the latin2 writing system */
       if ( load_flags & ( 1UL << 20 ) )
-        options = 2;
+        options = AF_SCRIPT_LTN2;
 #endif
 
       error = af_face_globals_get_metrics( loader->globals, gindex,
                                            options, &metrics );
       if ( !error )
       {
+#ifdef FT_CONFIG_OPTION_PIC
+        AF_FaceGlobals         globals              = loader->globals;
+#endif
+        AF_WritingSystemClass  writing_system_class =
+                                 AF_WRITING_SYSTEM_CLASSES_GET
+                                   [metrics->script_class->writing_system];
+
+
         loader->metrics = metrics;
 
-        if ( metrics->clazz->script_metrics_scale )
-          metrics->clazz->script_metrics_scale( metrics, &scaler );
+        if ( writing_system_class->script_metrics_scale )
+          writing_system_class->script_metrics_scale( metrics, &scaler );
         else
           metrics->scaler = scaler;
 
         load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
         load_flags &= ~FT_LOAD_RENDER;
 
-        if ( metrics->clazz->script_hints_init )
+        if ( writing_system_class->script_hints_init )
         {
-          error = metrics->clazz->script_hints_init( &loader->hints,
-                                                     metrics );
+          error = writing_system_class->script_hints_init( &loader->hints,
+                                                           metrics );
           if ( error )
             goto Exit;
         }
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 45e1448..92d696d 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -43,13 +43,10 @@
 
 
   /* forward declaration of PIC init functions from script classes */
-#include "aflatin.h"
-#ifdef FT_OPTION_AUTOFIT2
-#include "aflatin2.h"
-#endif
-#include "afcjk.h"
-#include "afdummy.h"
-#include "afindic.h"
+#undef  WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS )  /* empty */
+
+#include "afwrtsys.h"
 
 
   void
@@ -100,27 +97,31 @@
 
     FT_Init_Class_af_service_properties( &container->af_service_properties );
 
-    for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
-    {
+    for ( ss = 0; ss < AF_WRITING_SYSTEM_MAX - 1; ss++ )
+      container->af_writing_system_classes[ss] =
+        &container->af_writing_system_classes_rec[ss];
+    container->af_writing_system_classes[AF_WRITING_SYSTEM_MAX - 1] = NULL;
+
+    for ( ss = 0; ss < AF_SCRIPT_MAX - 1; ss++ )
       container->af_script_classes[ss] =
         &container->af_script_classes_rec[ss];
-    }
-    container->af_script_classes[AF_SCRIPT_CLASSES_COUNT - 1] = NULL;
+    container->af_script_classes[AF_SCRIPT_MAX - 1] = NULL;
 
-    /* add call to initialization function when you add new scripts */
+#undef  WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS )                             \
+        FT_Init_Class_af_ ## ws ## _writing_system_class(    \
+          &container->af_writing_system_classes_rec[ss++] );
+
     ss = 0;
-    FT_Init_Class_af_dummy_script_class(
-      &container->af_script_classes_rec[ss++] );
-#ifdef FT_OPTION_AUTOFIT2
-    FT_Init_Class_af_latin2_script_class(
-      &container->af_script_classes_rec[ss++] );
-#endif
-    FT_Init_Class_af_latin_script_class(
-      &container->af_script_classes_rec[ss++] );
-    FT_Init_Class_af_cjk_script_class(
-      &container->af_script_classes_rec[ss++] );
-    FT_Init_Class_af_indic_script_class(
-      &container->af_script_classes_rec[ss++] );
+#include "afwrtsys.h"
+
+#undef  SCRIPT
+#define SCRIPT( s, S, d )                            \
+        FT_Init_Class_af_ ## s ## _script_class(     \
+          &container->af_script_classes_rec[ss++] );
+
+    ss = 0;
+#include "afscript.h"
 
     FT_Init_Class_af_autofitter_interface(
       library, &container->af_autofitter_interface );
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 0acf803..09f8258 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-2012 by                                           */
+/*  Copyright 2009, 2011-2013 by                                           */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,11 +27,12 @@
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define AF_SERVICES_GET            af_services
-#define AF_SERVICE_PROPERTIES_GET  af_service_properties
+#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
+#define AF_WRITING_SYSTEM_CLASSES_GET  af_writing_system_classes
+#define AF_SCRIPT_CLASSES_GET          af_script_classes
+#define AF_INTERFACE_GET               af_autofitter_interface
 
 #else /* FT_CONFIG_OPTION_PIC */
 
@@ -40,24 +41,22 @@
 
 #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
-#else
-#define AF_SCRIPT_CLASSES_COUNT  5
-#endif
-
-#define AF_SCRIPT_CLASSES_REC_COUNT  ( AF_SCRIPT_CLASSES_COUNT - 1 )
-
 
   typedef struct  AFModulePIC_
   {
     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];
+    AF_WritingSystemClass       af_writing_system_classes
+                                  [AF_WRITING_SYSTEM_MAX];
+    AF_WritingSystemClassRec    af_writing_system_classes_rec
+                                  [AF_WRITING_SYSTEM_MAX - 1];
+
+    AF_ScriptClass              af_script_classes
+                                  [AF_SCRIPT_MAX];
+    AF_ScriptClassRec           af_script_classes_rec
+                                  [AF_SCRIPT_MAX - 1];
+
     FT_AutoHinter_InterfaceRec  af_autofitter_interface;
 
   } AFModulePIC;
@@ -71,6 +70,8 @@
 #define AF_SERVICE_PROPERTIES_GET  \
           ( GET_PIC( library )->af_service_properties )
 
+#define AF_WRITING_SYSTEM_CLASSES_GET  \
+          ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_writing_system_classes )
 #define AF_SCRIPT_CLASSES_GET  \
           ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_script_classes )
 #define AF_INTERFACE_GET  \
diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
new file mode 100644
index 0000000..32ec2ca
--- /dev/null
+++ b/src/autofit/afscript.h
@@ -0,0 +1,37 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afscript.h                                                             */
+/*                                                                         */
+/*    Auto-fitter scripts (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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /* The following part can be included multiple times. */
+  /* Define `SCRIPT' as needed.                         */
+
+
+  /* Add new scripts here. */
+
+  SCRIPT( cyrl, CYRL, "Cyrillic" )
+  SCRIPT( deva, DEVA, "Indic scripts" )
+  SCRIPT( none, NONE, "no script" )
+  SCRIPT( grek, GREK, "Greek" )
+  SCRIPT( hani, HANI, "CJKV ideographs" )
+  SCRIPT( hebr, HEBR, "Hebrew" )
+  SCRIPT( latn, LATN, "Latin" )
+#ifdef FT_OPTION_AUTOFIT2
+  SCRIPT( ltn2, LTN2, "Latin 2" )
+#endif
+
+
+/* END */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 9acd7ad..cda1f89 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter types (specification only).                              */
 /*                                                                         */
-/*  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,       */
@@ -20,15 +20,12 @@
    *
    *  The auto-fitter is a complete rewrite of the old auto-hinter.
    *  Its main feature is the ability to differentiate between different
-   *  scripts in order to apply language-specific rules.
+   *  writing systems in order to apply script-specific rules.
    *
    *  The code has also been compartmentized into several entities that
    *  should make algorithmic experimentation easier than with the old
    *  code.
    *
-   *  Finally, we get rid of the Catharon license, since this code is
-   *  released under the FreeType one.
-   *
    *************************************************************************/
 
 
@@ -42,6 +39,8 @@
 #include FT_INTERNAL_OBJECTS_H
 #include FT_INTERNAL_DEBUG_H
 
+#include "afblue.h"
+
 
 FT_BEGIN_HEADER
 
@@ -201,56 +200,21 @@
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
-  /*****                       S C R I P T S                           *****/
+  /*****                 S C R I P T   M E T R I C S                   *****/
   /*****                                                               *****/
   /*************************************************************************/
   /*************************************************************************/
 
-  /*
-   *  The list of known scripts.  Each different script corresponds to the
-   *  following information:
-   *
-   *   - A set of Unicode ranges to test whether the face supports the
-   *     script.
-   *
-   *   - A specific global analyzer that will compute global metrics
-   *     specific to the script.
-   *
-   *   - A specific glyph analyzer that will compute segments and
-   *     edges for each glyph covered by the script.
-   *
-   *   - A specific grid-fitting algorithm that will distort the
-   *     scaled glyph outline according to the results of the glyph
-   *     analyzer.
-   *
-   *  Note that a given analyzer and/or grid-fitting algorithm can be
-   *  used by more than one script.
-   */
+  /* This is the main structure which combines writing systems and script */
+  /* data (for a given face object, see below).                           */
 
-  typedef enum  AF_Script_
-  {
-    AF_SCRIPT_DUMMY = 0,
-    AF_SCRIPT_LATIN = 1,
-    AF_SCRIPT_CJK   = 2,
-    AF_SCRIPT_INDIC = 3,
-#ifdef FT_OPTION_AUTOFIT2
-    AF_SCRIPT_LATIN2 = 4,
-#endif
-
-    /* add new scripts here.  Don't forget to update the list in */
-    /* `afglobal.c'.                                             */
-
-    AF_SCRIPT_MAX   /* do not remove */
-
-  } AF_Script;
-
-
-  typedef struct AF_ScriptClassRec_ const*  AF_ScriptClass;
-  typedef struct AF_FaceGlobalsRec_*        AF_FaceGlobals;
+  typedef struct AF_WritingSystemClassRec_ const*  AF_WritingSystemClass;
+  typedef struct AF_ScriptClassRec_ const*         AF_ScriptClass;
+  typedef struct AF_FaceGlobalsRec_*               AF_FaceGlobals;
 
   typedef struct  AF_ScriptMetricsRec_
   {
-    AF_ScriptClass  clazz;
+    AF_ScriptClass  script_class;
     AF_ScalerRec    scaler;
     FT_Bool         digits_have_same_width;
 
@@ -284,23 +248,54 @@
                                AF_ScriptMetrics  metrics );
 
 
-  typedef struct  AF_Script_UniRangeRec_
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                W R I T I N G   S Y S T E M S                  *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*
+   *  In FreeType, a writing system consists of multiple scripts which can
+   *  be handled similarly *in a typographical way*; the relationship is not
+   *  based on history.  For example, both the Greek and the unrelated
+   *  Armenian scripts share the same features like ascender, descender,
+   *  x-height, etc.  Essentially, a writing system is covered by a
+   *  submodule of the auto-fitter; it contains
+   *
+   *  - a specific global analyzer which computes global metrics specific to
+   *    the script (based on script-specific characters to identify ascender
+   *    height, x-height, etc.),
+   *
+   *  - a specific glyph analyzer that computes segments and edges for each
+   *    glyph covered by the script,
+   *
+   *  - a specific grid-fitting algorithm that distorts the scaled glyph
+   *    outline according to the results of the glyph analyzer.
+   */
+
+#define __AFWRTSYS_H__  /* don't load header files */
+#undef  WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS )    \
+          AF_WRITING_SYSTEM_ ## WS,
+
+  /* The list of known writing systems. */
+  typedef enum  AF_WritingSystem_
   {
-    FT_UInt32  first;
-    FT_UInt32  last;
 
-  } AF_Script_UniRangeRec;
+#include "afwrtsys.h"
 
-#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }
+    AF_WRITING_SYSTEM_MAX   /* do not remove */
 
-  typedef const AF_Script_UniRangeRec  *AF_Script_UniRange;
+  } AF_WritingSystem;
+
+#undef  __AFWRTSYS_H__
 
 
-  typedef struct  AF_ScriptClassRec_
+  typedef struct  AF_WritingSystemClassRec_
   {
-    AF_Script           script;
-    AF_Script_UniRange  script_uni_ranges; /* last must be { 0, 0 }        */
-    FT_UInt32           standard_char;     /* for default width and height */
+    AF_WritingSystem  writing_system;
 
     FT_Offset                   script_metrics_size;
     AF_Script_InitMetricsFunc   script_metrics_init;
@@ -310,59 +305,167 @@
     AF_Script_InitHintsFunc     script_hints_init;
     AF_Script_ApplyHintsFunc    script_hints_apply;
 
+  } AF_WritingSystemClassRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                        S C R I P T S                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*
+   *  Each script is associated with a set of Unicode ranges which gets used
+   *  to test whether the font face supports the script.  It also references
+   *  the writing system it belongs to.
+   *
+   *  We use four-letter script tags from the OpenType specification.
+   */
+
+#undef  SCRIPT
+#define SCRIPT( s, S, d ) \
+          AF_SCRIPT_ ## S,
+
+  /* The list of known scripts. */
+  typedef enum  AF_Script_
+  {
+
+#include "afscript.h"
+
+    AF_SCRIPT_MAX   /* do not remove */
+
+  } AF_Script;
+
+
+  typedef struct  AF_Script_UniRangeRec_
+  {
+    FT_UInt32  first;
+    FT_UInt32  last;
+
+  } AF_Script_UniRangeRec;
+
+#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }
+
+  typedef const AF_Script_UniRangeRec*  AF_Script_UniRange;
+
+
+  typedef struct  AF_ScriptClassRec_
+  {
+    AF_Script          script;
+    AF_Blue_Stringset  blue_stringset;
+    AF_WritingSystem   writing_system;
+
+    AF_Script_UniRange  script_uni_ranges; /* last must be { 0, 0 }        */
+    FT_UInt32           standard_char;     /* for default width and height */
+
   } AF_ScriptClassRec;
 
 
   /* Declare and define vtables for classes */
 #ifndef FT_CONFIG_OPTION_PIC
 
+#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
+  FT_CALLBACK_TABLE const AF_WritingSystemClassRec              \
+  writing_system_class;
+
+#define AF_DEFINE_WRITING_SYSTEM_CLASS(                  \
+          writing_system_class,                          \
+          system,                                        \
+          m_size,                                        \
+          m_init,                                        \
+          m_scale,                                       \
+          m_done,                                        \
+          h_init,                                        \
+          h_apply )                                      \
+  FT_CALLBACK_TABLE_DEF                                  \
+  const AF_WritingSystemClassRec  writing_system_class = \
+  {                                                      \
+    system,                                              \
+                                                         \
+    m_size,                                              \
+                                                         \
+    m_init,                                              \
+    m_scale,                                             \
+    m_done,                                              \
+                                                         \
+    h_init,                                              \
+    h_apply                                              \
+  };
+
+
 #define AF_DECLARE_SCRIPT_CLASS( script_class ) \
   FT_CALLBACK_TABLE const AF_ScriptClassRec     \
   script_class;
 
-#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 =            \
-  {                                                                        \
-    script_,                                                               \
-    ranges,                                                                \
-    def_char,                                                              \
-                                                                           \
-    m_size,                                                                \
-                                                                           \
-    m_init,                                                                \
-    m_scale,                                                               \
-    m_done,                                                                \
-                                                                           \
-    h_init,                                                                \
-    h_apply                                                                \
+#define AF_DEFINE_SCRIPT_CLASS(           \
+          script_class,                   \
+          script_,                        \
+          blue_stringset_,                \
+          writing_system_,                \
+          ranges,                         \
+          std_char )                      \
+  FT_CALLBACK_TABLE_DEF                   \
+  const AF_ScriptClassRec  script_class = \
+  {                                       \
+    script_,                              \
+    blue_stringset_,                      \
+    writing_system_,                      \
+    ranges,                               \
+    std_char                              \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
+#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class )            \
+  FT_LOCAL( void )                                                         \
+  FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec*  ac );
+
+#define AF_DEFINE_WRITING_SYSTEM_CLASS(                                   \
+          writing_system_class,                                           \
+          system,                                                         \
+          m_size,                                                         \
+          m_init,                                                         \
+          m_scale,                                                        \
+          m_done,                                                         \
+          h_init,                                                         \
+          h_apply )                                                       \
+  FT_LOCAL_DEF( void )                                                    \
+  FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec*  ac ) \
+  {                                                                       \
+    ac->writing_system       = system;                                    \
+                                                                          \
+    ac->script_metrics_size  = m_size;                                    \
+                                                                          \
+    ac->script_metrics_init  = m_init;                                    \
+    ac->script_metrics_scale = m_scale;                                   \
+    ac->script_metrics_done  = m_done;                                    \
+                                                                          \
+    ac->script_hints_init    = h_init;                                    \
+    ac->script_hints_apply   = h_apply;                                   \
+  }
+
+
 #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, 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 )                 \
-  {                                                                        \
-    ac->script               = script_;                                    \
-    ac->script_uni_ranges    = ranges;                                     \
-    ac->default_char         = def_char;                                   \
-                                                                           \
-    ac->script_metrics_size  = m_size;                                     \
-                                                                           \
-    ac->script_metrics_init  = m_init;                                     \
-    ac->script_metrics_scale = m_scale;                                    \
-    ac->script_metrics_done  = m_done;                                     \
-                                                                           \
-    ac->script_hints_init    = h_init;                                     \
-    ac->script_hints_apply   = h_apply;                                    \
+#define AF_DEFINE_SCRIPT_CLASS(                            \
+          script_class,                                    \
+          script_,                                         \
+          blue_string_set_,                                \
+          writing_system_,                                 \
+          ranges,                                          \
+          std_char )                                       \
+  FT_LOCAL_DEF( void )                                     \
+  FT_Init_Class_ ## script_class( AF_ScriptClassRec*  ac ) \
+  {                                                        \
+    ac->script            = script_;                       \
+    ac->blue_stringset    = blue_stringset_;               \
+    ac->writing_system    = writing_system_;               \
+    ac->script_uni_ranges = ranges;                        \
+    ac->standard_char     = std_char;                      \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
diff --git a/src/autofit/afwrtsys.h b/src/autofit/afwrtsys.h
new file mode 100644
index 0000000..602c558
--- /dev/null
+++ b/src/autofit/afwrtsys.h
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afwrtsys.h                                                             */
+/*                                                                         */
+/*    Auto-fitter writing systems (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 __AFWRTSYS_H__
+#define __AFWRTSYS_H__
+
+  /* Since preprocessor directives can't create other preprocessor */
+  /* directives, we have to include the header files manually.     */
+
+#include "afdummy.h"
+#include "aflatin.h"
+#include "afcjk.h"
+#include "afindic.h"
+#ifdef FT_OPTION_AUTOFIT2
+#include "aflatin2.h"
+#endif
+
+#endif /* __AFWRTSYS_H__ */
+
+
+  /* The following part can be included multiple times. */
+  /* Define `WRITING_SYSTEM' as needed.                 */
+
+
+  /* Add new writing systems here. */
+
+  WRITING_SYSTEM( dummy,  DUMMY  )
+  WRITING_SYSTEM( latin,  LATIN  )
+  WRITING_SYSTEM( cjk,    CJK    )
+  WRITING_SYSTEM( indic,  INDIC  )
+#ifdef FT_OPTION_AUTOFIT2
+  WRITING_SYSTEM( latin2, LATIN2 )
+#endif
+
+
+/* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index 3883a0a..b23374a 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module (body).                                           */
 /*                                                                         */
-/*  Copyright 2003-2007, 2011 by                                           */
+/*  Copyright 2003-2007, 2011, 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 <ft2build.h>
 #include "afpic.c"
 #include "afangles.c"
+#include "afblue.c"
 #include "afglobal.c"
 #include "afhints.c"
 
diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
index 6d1c44c..8d3f383 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -85,7 +85,7 @@
   /*    BBox_Conic_Check                                                   */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Finds the extrema of a 1-dimensional conic Bezier curve and update */
+  /*    Find the extrema of a 1-dimensional conic Bezier curve and update  */
   /*    a bounding range.  This version uses direct computation, as it     */
   /*    doesn't need square roots.                                         */
   /*                                                                       */
@@ -108,30 +108,19 @@
                     FT_Pos*  min,
                     FT_Pos*  max )
   {
-    if ( y1 <= y3 && y2 == y1 )     /* flat arc */
-      goto Suite;
+    /* This function is only called when a control off-point is outside */
+    /* the bbox that contains all on-points.  It finds a local extremum */
+    /* within the segment, equal to (y1*y3 - y2*y2)/(y1 - 2*y2 + y3).   */
+    /* Or, offsetting from y2, we get                                   */
 
-    if ( y1 < y3 )
-    {
-      if ( y2 >= y1 && y2 <= y3 )   /* ascending arc */
-        goto Suite;
-    }
-    else
-    {
-      if ( y2 >= y3 && y2 <= y1 )   /* descending arc */
-      {
-        y2 = y1;
-        y1 = y3;
-        y3 = y2;
-        goto Suite;
-      }
-    }
+    y1 -= y2;
+    y3 -= y2;
+    y2 += FT_MulDiv( y1, y3, y1 + y3 );
 
-    y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
-
-  Suite:
-    if ( y1 < *min ) *min = y1;
-    if ( y3 > *max ) *max = y3;
+    if ( y2 < *min )
+      *min = y2;
+    if ( y2 > *max )
+      *max = y2;
   }
 
 
@@ -195,9 +184,9 @@
   /*    BBox_Cubic_Check                                                   */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Finds the extrema of a 1-dimensional cubic Bezier curve and        */
-  /*    updates a bounding range.  This version uses splitting because we  */
-  /*    don't want to use square roots and extra accuracy.                 */
+  /*    Find the extrema of a 1-dimensional cubic Bezier curve and         */
+  /*    update a bounding range.  This version uses iterative splitting    */
+  /*    because it is faster than the exact solution with square roots.    */
   /*                                                                       */
   /* <Input>                                                               */
   /*    p1  :: The start coordinate.                                       */
@@ -213,28 +202,16 @@
   /*                                                                       */
   /*    max :: The address of the current maximum.                         */
   /*                                                                       */
-
-#if 0
-
-  static void
-  BBox_Cubic_Check( FT_Pos   p1,
-                    FT_Pos   p2,
-                    FT_Pos   p3,
-                    FT_Pos   p4,
-                    FT_Pos*  min,
-                    FT_Pos*  max )
+  static FT_Pos
+  update_cubic_max( FT_Pos  q1,
+                    FT_Pos  q2,
+                    FT_Pos  q3,
+                    FT_Pos  q4,
+                    FT_Pos  max )
   {
-    FT_Pos  q1, q2, q3, q4;
-
-
-    q1 = p1;
-    q2 = p2;
-    q3 = p3;
-    q4 = p4;
-
-    /* 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 )
+    /* for a cubic segment to possibly reach new maximum, at least */
+    /* one of its off-points must stay above the current value     */
+    while ( q2 > max || q3 > max )
     {
       /* determine which half contains the maximum and split */
       if ( q1 + q2 > q3 + q4 ) /* first half */
@@ -260,232 +237,92 @@
         q3 = q3 / 2;
       }
 
-      /* check if either end reached the maximum */
+      /* check whether either end reached the maximum */
       if ( q1 == q2 && q1 >= q3 )
       {
-        *max = q1;
+        max = q1;
         break;
       }
       if ( q3 == q4 && q2 <= q4 )
       {
-        *max = q4;
+        max = q4;
         break;
       }
     }
 
-    q1 = p1;
-    q2 = p2;
-    q3 = p3;
-    q4 = p4;
-
-    /* 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;
-      }
-
-      /* check if either end reached the minimum */
-      if ( q1 == q2 && q1 <= q3 )
-      {
-        *min = q1;
-        break;
-      }
-      if ( q3 == q4 && q2 >= q4 )
-      {
-        *min = q4;
-        break;
-      }
-    }
-  }
-
-#else
-
-  static void
-  test_cubic_extrema( FT_Pos    y1,
-                      FT_Pos    y2,
-                      FT_Pos    y3,
-                      FT_Pos    y4,
-                      FT_Fixed  u,
-                      FT_Pos*   min,
-                      FT_Pos*   max )
-  {
- /* FT_Pos    a = y4 - 3*y3 + 3*y2 - y1; */
-    FT_Pos    b = y3 - 2*y2 + y1;
-    FT_Pos    c = y2 - y1;
-    FT_Pos    d = y1;
-    FT_Pos    y;
-    FT_Fixed  uu;
-
-    FT_UNUSED ( y4 );
-
-
-    /* The polynomial is                      */
-    /*                                        */
-    /*    P(x) = a*x^3 + 3b*x^2 + 3c*x + d  , */
-    /*                                        */
-    /*   dP/dx = 3a*x^2 + 6b*x + 3c         . */
-    /*                                        */
-    /* However, we also have                  */
-    /*                                        */
-    /*   dP/dx(u) = 0                       , */
-    /*                                        */
-    /* which implies by subtraction that      */
-    /*                                        */
-    /*   P(u) = b*u^2 + 2c*u + d            . */
-
-    if ( u > 0 && u < 0x10000L )
-    {
-      uu = FT_MulFix( u, u );
-      y  = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
-
-      if ( y < *min ) *min = y;
-      if ( y > *max ) *max = y;
-    }
+    return max;
   }
 
 
   static void
-  BBox_Cubic_Check( FT_Pos   y1,
-                    FT_Pos   y2,
-                    FT_Pos   y3,
-                    FT_Pos   y4,
+  BBox_Cubic_Check( FT_Pos   p1,
+                    FT_Pos   p2,
+                    FT_Pos   p3,
+                    FT_Pos   p4,
                     FT_Pos*  min,
                     FT_Pos*  max )
   {
-    /* always compare first and last points */
-    if      ( y1 < *min )  *min = y1;
-    else if ( y1 > *max )  *max = y1;
+    FT_Pos  nmin, nmax;
+    FT_Int  shift;
 
-    if      ( y4 < *min )  *min = y4;
-    else if ( y4 > *max )  *max = y4;
 
-    /* now, try to see if there are split points here */
-    if ( y1 <= y4 )
+    /* This function is only called when a control off-point is outside  */
+    /* the bbox that contains all on-points.  It finds a local extremum  */
+    /* within the segment using iterative bisection of the segment.      */
+    /* The fixed-point arithmetic of bisection is inherently stable      */
+    /* but may loose accuracy in the two lowest bits.  To compensate,    */
+    /* we upscale the segment if there is room.  Large values may need   */
+    /* to be downscaled to avoid overflows during bisection.             */
+    /* The control off-point outside the bbox is likely to have the top  */
+    /* absolute value among arguments.                                   */
+
+    shift = 27 - FT_MSB( FT_ABS( p2 ) | FT_ABS( p3 ) );
+
+    if ( shift > 0 )
     {
-      /* flat or ascending arc test */
-      if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
-        return;
+      /* upscaling too much just wastes time */
+      if ( shift > 2 )
+        shift = 2;
+
+      p1 <<=  shift;
+      p2 <<=  shift;
+      p3 <<=  shift;
+      p4 <<=  shift;
+      nmin = *min << shift;
+      nmax = *max << shift;
     }
-    else /* y1 > y4 */
+    else
     {
-      /* descending arc test */
-      if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
-        return;
+      p1 >>= -shift;
+      p2 >>= -shift;
+      p3 >>= -shift;
+      p4 >>= -shift;
+      nmin = *min >> -shift;
+      nmax = *max >> -shift;
     }
 
-    /* There are some split points.  Find them.                        */
-    /* We already made sure that a, b, and c below cannot be all zero. */
+    nmax =  update_cubic_max(  p1,  p2,  p3,  p4,  nmax );
+
+    /* now flip the signs to update the minimum */
+    nmin = -update_cubic_max( -p1, -p2, -p3, -p4, -nmin );
+
+    if ( shift > 0 )
     {
-      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.                            */
-      /*                                                                   */
-      /* 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-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 )
-      {
-        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;
-
-        a <<= shift;
-        b <<= shift;
-        c <<= shift;
-      }
-
-      /* handle a == 0 */
-      if ( a == 0 )
-      {
-        if ( b != 0 )
-        {
-          t = - FT_DivFix( c, b ) / 2;
-          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
-        }
-      }
-      else
-      {
-        /* solve the equation now */
-        d = FT_MulFix( b, b ) - FT_MulFix( a, c );
-        if ( d < 0 )
-          return;
-
-        if ( d == 0 )
-        {
-          /* there is a single split point at -b/a */
-          t = - FT_DivFix( b, a );
-          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
-        }
-        else
-        {
-          /* there are two solutions; we need to filter them */
-          d = FT_SqrtFixed( (FT_Int32)d );
-          t = - FT_DivFix( b - d, a );
-          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
-
-          t = - FT_DivFix( b + d, a );
-          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
-        }
-      }
+      nmin >>=  shift;
+      nmax >>=  shift;
     }
+    else
+    {
+      nmin <<= -shift;
+      nmax <<= -shift;
+    }
+
+    if ( nmin < *min )
+      *min = nmin;
+    if ( nmax > *max )
+      *max = nmax;
   }
 
-#endif
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -521,8 +358,9 @@
                  FT_Vector*  to,
                  TBBox_Rec*  user )
   {
-    /* we don't need to check `to' since it is always an `on' point, thus */
-    /* within the bbox                                                    */
+    /* We don't need to check `to' since it is always an on-point,    */
+    /* thus within the bbox.  Only segments with an off-point outside */
+    /* the bbox can possibly reach new extreme values.                */
 
     if ( CHECK_X( control1, user->bbox ) ||
          CHECK_X( control2, user->bbox ) )
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 975818e..182b1cc 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -385,6 +385,10 @@
     FT_Long  l;
 
 
+    /* Short-circuit transparent color to avoid div-by-zero. */
+    if ( !a )
+      return 0;
+
     /*
      * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
      * coefficients for RGB channels *on the linear colors*.
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index 0ec0d78..b23b4d4 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -816,6 +816,8 @@
   }
 
 
+#if 0
+
   /* documentation is in ftcalc.h */
 
   FT_BASE_DEF( FT_Int32 )
@@ -850,6 +852,8 @@
     return (FT_Int32)root;
   }
 
+#endif /* 0 */
+
 
   /* documentation is in ftcalc.h */
 
@@ -945,11 +949,27 @@
     FT_Pos  d_in, d_out, d_corner;
 
 
+    /* We approximate the Euclidean metric (sqrt(x^2 + y^2)) with */
+    /* the Taxicab metric (|x| + |y|), which can be computed much */
+    /* faster.  If one of the two vectors is much longer than the */
+    /* other one, the direction of the shorter vector doesn't     */
+    /* influence the result any more.                             */
+    /*                                                            */
+    /*                 corner                                     */
+    /*       x---------------------------x                        */
+    /*        \                      /                            */
+    /*         \                /                                 */
+    /*      in  \          /  out                                 */
+    /*           \    /                                           */
+    /*            o                                               */
+    /*              Point                                         */
+    /*                                                            */
+
     if ( ax < 0 )
       ax = -ax;
     if ( ay < 0 )
       ay = -ay;
-    d_in = ax + ay;
+    d_in = ax + ay;  /* d_in = || in || */
 
     ax = out_x;
     if ( ax < 0 )
@@ -957,7 +977,7 @@
     ay = out_y;
     if ( ay < 0 )
       ay = -ay;
-    d_out = ax + ay;
+    d_out = ax + ay;  /* d_out = || out || */
 
     ax = out_x + in_x;
     if ( ax < 0 )
@@ -965,7 +985,11 @@
     ay = out_y + in_y;
     if ( ay < 0 )
       ay = -ay;
-    d_corner = ax + ay;
+    d_corner = ax + ay;  /* d_corner = || in + out || */
+
+    /* now do a simple length comparison: */
+    /*                                    */
+    /*   d_in + d_out < 17/16 d_corner    */
 
     return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
   }
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index b9156d1..39ac6ad 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -152,7 +152,7 @@
   /* the memory and stream components which are set to 7 and 5,            */
   /* respectively.                                                         */
   /*                                                                       */
-  /* See the file <include/freetype/internal/fttrace.h> for details of the */
+  /* See the file <include/internal/fttrace.h> for details of the          */
   /* available toggle names.                                               */
   /*                                                                       */
   /* The level must be between 0 and 7; 0 means quiet (except for serious  */
diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c
index 663db26..3cc5c7a 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -265,6 +265,9 @@
       FT_GlyphLoader_Adjust_Points( loader );
 
   Exit:
+    if ( error )
+      FT_GlyphLoader_Reset( loader );
+
     return error;
   }
 
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index 5dd28a8..c62b3db 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -424,15 +424,16 @@
                       FT_Matrix*  matrix,
                       FT_Vector*  delta )
   {
-    const FT_Glyph_Class*  clazz;
-    FT_Error               error = FT_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( !glyph || !glyph->clazz )
       error = FT_THROW( Invalid_Argument );
     else
     {
-      clazz = glyph->clazz;
+      const FT_Glyph_Class*  clazz = glyph->clazz;
+
+
       if ( clazz->glyph_transform )
       {
         /* transform glyph image */
@@ -466,38 +467,33 @@
 
     if ( !glyph || !glyph->clazz )
       return;
-    else
+
+    clazz = glyph->clazz;
+    if ( !clazz->glyph_bbox )
+      return;
+
+    /* retrieve bbox in 26.6 coordinates */
+    clazz->glyph_bbox( glyph, acbox );
+
+    /* perform grid fitting if needed */
+    if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
+         bbox_mode == FT_GLYPH_BBOX_PIXELS  )
     {
-      clazz = glyph->clazz;
-      if ( !clazz->glyph_bbox )
-        return;
-      else
-      {
-        /* retrieve bbox in 26.6 coordinates */
-        clazz->glyph_bbox( glyph, acbox );
-
-        /* perform grid fitting if needed */
-        if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
-             bbox_mode == FT_GLYPH_BBOX_PIXELS  )
-        {
-          acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
-          acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
-          acbox->xMax = FT_PIX_CEIL( acbox->xMax );
-          acbox->yMax = FT_PIX_CEIL( acbox->yMax );
-        }
-
-        /* convert to integer pixels if needed */
-        if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
-             bbox_mode == FT_GLYPH_BBOX_PIXELS   )
-        {
-          acbox->xMin >>= 6;
-          acbox->yMin >>= 6;
-          acbox->xMax >>= 6;
-          acbox->yMax >>= 6;
-        }
-      }
+      acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
+      acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
+      acbox->xMax = FT_PIX_CEIL( acbox->xMax );
+      acbox->yMax = FT_PIX_CEIL( acbox->yMax );
     }
-    return;
+
+    /* convert to integer pixels if needed */
+    if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
+         bbox_mode == FT_GLYPH_BBOX_PIXELS   )
+    {
+      acbox->xMin >>= 6;
+      acbox->yMin >>= 6;
+      acbox->xMax >>= 6;
+      acbox->yMax >>= 6;
+    }
   }
 
 
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index 85f321f..6176273 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -23,8 +23,8 @@
   /*  FT_Add_Default_Modules():                                            */
   /*     This function is used to add the set of default modules to a      */
   /*     fresh new library object.  The set is taken from the header file  */
-  /*     `freetype/config/ftmodule.h'.  See the document `FreeType 2.0     */
-  /*     Build System' for more information.                               */
+  /*     `config/ftmodule.h'.  See the document `FreeType 2.0 Build        */
+  /*     System' for more information.                                     */
   /*                                                                       */
   /*  FT_Init_FreeType():                                                  */
   /*     This function creates a system object for the current platform,   */
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index ac2a39c..bd0c66e 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -56,9 +56,7 @@
 #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 )
@@ -667,11 +665,18 @@
 
         /* the check for `num_locations' assures that we actually    */
         /* test for instructions in a TTF and not in a CFF-based OTF */
+        /*                                                           */
+        /* since `maxSizeOfInstructions' might be unreliable, we     */
+        /* check the size of the `fpgm' and `prep' tables, too --    */
+        /* the assumption is that there don't exist real TTFs where  */
+        /* both `fpgm' and `prep' tables are missing                 */
         if ( mode == FT_RENDER_MODE_LIGHT                       ||
              face->internal->ignore_unpatented_hinter           ||
              ( FT_IS_SFNT( face )                             &&
                ttface->num_locations                          &&
-               ttface->max_profile.maxSizeOfInstructions == 0 ) )
+               ttface->max_profile.maxSizeOfInstructions == 0 &&
+               ttface->font_program_size == 0                 &&
+               ttface->cvt_program_size == 0                  ) )
           autohint = TRUE;
       }
     }
@@ -1133,7 +1138,8 @@
   /*                                                                       */
   static FT_Error
   open_face( FT_Driver      driver,
-             FT_Stream      stream,
+             FT_Stream      *astream,
+             FT_Bool        external_stream,
              FT_Long        face_index,
              FT_Int         num_params,
              FT_Parameter*  params,
@@ -1141,10 +1147,11 @@
   {
     FT_Memory         memory;
     FT_Driver_Class   clazz;
-    FT_Face           face = 0;
-    FT_Error          error, error2;
+    FT_Face           face     = NULL;
     FT_Face_Internal  internal = NULL;
 
+    FT_Error          error, error2;
+
 
     clazz  = driver->clazz;
     memory = driver->root.memory;
@@ -1153,15 +1160,19 @@
     if ( FT_ALLOC( face, clazz->face_object_size ) )
       goto Fail;
 
+    face->driver = driver;
+    face->memory = memory;
+    face->stream = *astream;
+
+    /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+    if ( external_stream )
+      face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
     if ( FT_NEW( internal ) )
       goto Fail;
 
     face->internal = internal;
 
-    face->driver   = driver;
-    face->memory   = memory;
-    face->stream   = stream;
-
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     {
       int  i;
@@ -1177,11 +1188,12 @@
 #endif
 
     if ( clazz->init_face )
-      error = clazz->init_face( stream,
+      error = clazz->init_face( *astream,
                                 face,
                                 (FT_Int)face_index,
                                 num_params,
                                 params );
+    *astream = face->stream; /* Stream may have been changed. */
     if ( error )
       goto Fail;
 
@@ -2024,8 +2036,8 @@
                 FT_Face             *aface )
   {
     FT_Error     error;
-    FT_Driver    driver;
-    FT_Memory    memory;
+    FT_Driver    driver = NULL;
+    FT_Memory    memory = NULL;
     FT_Stream    stream = NULL;
     FT_Face      face   = NULL;
     FT_ListNode  node   = NULL;
@@ -2069,7 +2081,7 @@
           params     = args->params;
         }
 
-        error = open_face( driver, stream, face_index,
+        error = open_face( driver, &stream, external_stream, face_index,
                            num_params, params, &face );
         if ( !error )
           goto Success;
@@ -2105,7 +2117,7 @@
             params     = args->params;
           }
 
-          error = open_face( driver, stream, face_index,
+          error = open_face( driver, &stream, external_stream, face_index,
                              num_params, params, &face );
           if ( !error )
             goto Success;
@@ -2174,10 +2186,6 @@
   Success:
     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
 
-    /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
-    if ( external_stream )
-      face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
-
     /* add the face object to its driver's list */
     if ( FT_NEW( node ) )
       goto Fail;
@@ -2265,7 +2273,10 @@
     goto Exit;
 
   Fail:
-    FT_Done_Face( face );
+    if ( node )
+      FT_Done_Face( face );    /* face must be in the driver's list */
+    else if ( face )
+      destroy_face( memory, face, driver );
 
   Exit:
     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
@@ -3377,8 +3388,10 @@
       FT_CMap    cmap = FT_CMAP( face->charmap );
 
 
-      do {
+      do
+      {
         gindex = cmap->clazz->char_next( cmap, &code );
+
       } while ( gindex >= (FT_UInt)face->num_glyphs );
 
       result = ( gindex == 0 ) ? 0 : code;
@@ -4308,7 +4321,8 @@
       FT_Renderer  renderer = FT_RENDERER( module );
 
 
-      if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
+      if ( renderer->clazz                                          &&
+           renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
            renderer->raster                                         )
         renderer->clazz->raster_class->raster_done( renderer->raster );
     }
@@ -4513,9 +4527,9 @@
     service = (FT_Service_Properties)interface;
 
     if ( set )
-      missing_func = !service->set_property;
+      missing_func = (FT_Bool)( !service->set_property );
     else
-      missing_func = !service->get_property;
+      missing_func = (FT_Bool)( !service->get_property );
 
     if ( missing_func )
     {
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 54ca5cd..35df0cd 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -576,11 +576,13 @@
       {
         char*  p = outline->tags + first;
         char*  q = outline->tags + last;
-        char   swap;
 
 
         while ( p < q )
         {
+          char  swap;
+
+
           swap = *p;
           *p   = *q;
           *q   = swap;
@@ -721,7 +723,8 @@
 #if 0
 
 #define FT_OUTLINE_GET_CONTOUR( outline, c, first, last )  \
-  do {                                                     \
+  do                                                       \
+  {                                                        \
     (first) = ( c > 0 ) ? (outline)->points +              \
                             (outline)->contours[c - 1] + 1 \
                         : (outline)->points;               \
diff --git a/src/base/ftpic.c b/src/base/ftpic.c
index 1c87101..9bd92f7 100644
--- a/src/base/ftpic.c
+++ b/src/base/ftpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services (body).              */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2013 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,7 +29,7 @@
   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_MEM_SET( pic_container, 0, sizeof ( *pic_container ) );
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index 241d37f..3098a60 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-2006, 2010, 2012 by                                     */
+/*  Copyright 2000-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,       */
@@ -139,10 +139,11 @@
     if ( slot->advance.y )
       slot->advance.y += ystr;
 
-    slot->metrics.width       += xstr;
-    slot->metrics.height      += ystr;
-    slot->metrics.horiAdvance += xstr;
-    slot->metrics.vertAdvance += ystr;
+    slot->metrics.width        += xstr;
+    slot->metrics.height       += ystr;
+    slot->metrics.horiAdvance  += xstr;
+    slot->metrics.vertAdvance  += ystr;
+    slot->metrics.horiBearingY += ystr;
 
     /* XXX: 16-bit overflow case must be excluded before here */
     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
diff --git a/src/base/md5.c b/src/base/md5.c
index 2f01c93..52d96ac 100644
--- a/src/base/md5.c
+++ b/src/base/md5.c
@@ -50,7 +50,8 @@
  */
 #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 H(x, y, z)			(((x) ^ (y)) ^ (z))
+#define H2(x, y, z)			((x) ^ ((y) ^ (z)))
 #define I(x, y, z)			((y) ^ ((x) | ~(z)))
 
 /*
@@ -89,13 +90,13 @@
  * 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)
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 {
-	unsigned char *ptr;
+	const unsigned char *ptr;
 	MD5_u32plus a, b, c, d;
 	MD5_u32plus saved_a, saved_b, saved_c, saved_d;
 
-	ptr = (unsigned char *)data;
+	ptr = (const unsigned char *)data;
 
 	a = ctx->a;
 	b = ctx->b;
@@ -146,21 +147,21 @@
 
 /* Round 3 */
 		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
-		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
+		STEP(H2, 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(H2, 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(H2, 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(H2, 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(H2, 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(H2, 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(H2, 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)
+		STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
 
 /* Round 4 */
 		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
@@ -207,10 +208,10 @@
 	ctx->hi = 0;
 }
 
-void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
 {
 	MD5_u32plus saved_lo;
-	unsigned long used, free;
+	unsigned long used, available;
 
 	saved_lo = ctx->lo;
 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
@@ -220,16 +221,16 @@
 	used = saved_lo & 0x3f;
 
 	if (used) {
-		free = 64 - used;
+		available = 64 - used;
 
-		if (size < free) {
+		if (size < available) {
 			memcpy(&ctx->buffer[used], data, size);
 			return;
 		}
 
-		memcpy(&ctx->buffer[used], data, free);
-		data = (unsigned char *)data + free;
-		size -= free;
+		memcpy(&ctx->buffer[used], data, available);
+		data = (const unsigned char *)data + available;
+		size -= available;
 		body(ctx, ctx->buffer, 64);
 	}
 
@@ -243,22 +244,22 @@
 
 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
 {
-	unsigned long used, free;
+	unsigned long used, available;
 
 	used = ctx->lo & 0x3f;
 
 	ctx->buffer[used++] = 0x80;
 
-	free = 64 - used;
+	available = 64 - used;
 
-	if (free < 8) {
-		memset(&ctx->buffer[used], 0, free);
+	if (available < 8) {
+		memset(&ctx->buffer[used], 0, available);
 		body(ctx, ctx->buffer, 64);
 		used = 0;
-		free = 64;
+		available = 64;
 	}
 
-	memset(&ctx->buffer[used], 0, free - 8);
+	memset(&ctx->buffer[used], 0, available - 8);
 
 	ctx->lo <<= 3;
 	ctx->buffer[56] = ctx->lo;
diff --git a/src/base/md5.h b/src/base/md5.h
index f1a6857..2da44bf 100644
--- a/src/base/md5.h
+++ b/src/base/md5.h
@@ -39,7 +39,7 @@
 } MD5_CTX;
 
 extern void MD5_Init(MD5_CTX *ctx);
-extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
 extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
 
 #endif
diff --git a/src/cff/cf2blues.c b/src/cff/cf2blues.c
index 5b34839..eec589e 100644
--- a/src/cff/cf2blues.c
+++ b/src/cff/cf2blues.c
@@ -86,11 +86,13 @@
     size_t     i;
     CF2_Fixed  emBoxBottom, emBoxTop;
 
+#if 0
     CF2_Int  unitsPerEm = font->unitsPerEm;
 
 
     if ( unitsPerEm == 0 )
       unitsPerEm = 1000;
+#endif
 
     FT_ZERO( blues );
     blues->scale = font->innerTransform.d;
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
index 8b2331d..718d1e2 100644
--- a/src/cff/cf2font.c
+++ b/src/cff/cf2font.c
@@ -51,10 +51,59 @@
                         CF2_Fixed   stemWidth,
                         CF2_Fixed*  darkenAmount,
                         CF2_Fixed   boldenAmount,
-                        FT_Bool     stemDarkened )
+                        FT_Bool     stemDarkened,
+                        FT_Int*     darkenParams )
   {
+    /*
+     * Total darkening amount is computed in 1000 unit character space
+     * using the modified 5 part curve as Adobe's Avalon rasterizer.
+     * The darkening amount is smaller for thicker stems.
+     * It becomes zero when the stem is thicker than 2.333 pixels.
+     *
+     * By default, we use
+     *
+     *   darkenAmount = 0.4 pixels   if scaledStem <= 0.5 pixels,
+     *   darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
+     *   darkenAmount = 0 pixel      if scaledStem >= 2.333 pixels,
+     *
+     * and piecewise linear in-between:
+     *
+     *
+     *   darkening
+     *       ^
+     *       |
+     *       |      (x1,y1)
+     *       |--------+
+     *       |         \
+     *       |          \
+     *       |           \          (x3,y3)
+     *       |            +----------+
+     *       |        (x2,y2)         \
+     *       |                         \
+     *       |                          \
+     *       |                           +-----------------
+     *       |                         (x4,y4)
+     *       +--------------------------------------------->   stem
+     *                                                       thickness
+     *
+     *
+     * This corresponds to the following values for the
+     * `darkening-parameters' property:
+     *
+     *   (x1, y1) = (500, 400)
+     *   (x2, y2) = (1000, 275)
+     *   (x3, y3) = (1667, 275)
+     *   (x4, y4) = (2333, 0)
+     *
+     */
+
     /* Internal calculations are done in units per thousand for */
-    /* convenience.                                             */
+    /* convenience. The x axis is scaled stem width in          */
+    /* thousandths of a pixel. That is, 1000 is 1 pixel.        */
+    /* The y axis is darkening amount in thousandths of a pixel.*/
+    /* In the code, below, dividing by ppem and                 */
+    /* adjusting for emRatio converts darkenAmount to character */
+    /* space (font units).                                      */
     CF2_Fixed  stemWidthPer1000, scaledStem;
 
 
@@ -69,6 +118,16 @@
 
     if ( stemDarkened )
     {
+      FT_Int  x1 = darkenParams[0];
+      FT_Int  y1 = darkenParams[1];
+      FT_Int  x2 = darkenParams[2];
+      FT_Int  y2 = darkenParams[3];
+      FT_Int  x3 = darkenParams[4];
+      FT_Int  y3 = darkenParams[5];
+      FT_Int  x4 = darkenParams[6];
+      FT_Int  y4 = darkenParams[7];
+
+
       /* convert from true character space to 1000 unit character space; */
       /* add synthetic emboldening effect                                */
 
@@ -81,7 +140,7 @@
            stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
       {
         stemWidthPer1000 = 0;                      /* to pacify compiler */
-        scaledStem       = cf2_intToFixed( 2333 );
+        scaledStem       = cf2_intToFixed( x4 );
       }
       else
       {
@@ -89,39 +148,70 @@
 
         if ( ppem > CF2_FIXED_ONE           &&
              scaledStem <= stemWidthPer1000 )
-          scaledStem = cf2_intToFixed( 2333 );
+          scaledStem = cf2_intToFixed( x4 );
       }
 
-      /*
-       * 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 );
+      /* now apply the darkening parameters */
 
-      else if ( scaledStem < cf2_intToFixed( 1000 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
-                          FT_MulFix( stemWidthPer1000,
-                                     cf2_floatToFixed( .25 ) );
+      if ( scaledStem < cf2_intToFixed( x1 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
 
-      else if ( scaledStem < cf2_intToFixed( 1667 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
+      else if ( scaledStem < cf2_intToFixed( x2 ) )
+      {
+        FT_Int  xdelta = x2 - x1;
+        FT_Int  ydelta = y2 - y1;
+        FT_Int  x      = stemWidthPer1000 -
+                           FT_DivFix( cf2_intToFixed( x1 ), ppem );
 
-      else if ( scaledStem < cf2_intToFixed( 2333 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
-                          FT_MulFix( stemWidthPer1000,
-                                     cf2_floatToFixed( .413 ) );
+
+        if ( !xdelta )
+          goto Try_x3;
+
+        *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                          FT_DivFix( cf2_intToFixed( y1 ), ppem );
+      }
+
+      else if ( scaledStem < cf2_intToFixed( x3 ) )
+      {
+      Try_x3:
+        {
+          FT_Int  xdelta = x3 - x2;
+          FT_Int  ydelta = y3 - y2;
+          FT_Int  x      = stemWidthPer1000 -
+                             FT_DivFix( cf2_intToFixed( x2 ), ppem );
+
+
+          if ( !xdelta )
+            goto Try_x4;
+
+          *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                            FT_DivFix( cf2_intToFixed( y2 ), ppem );
+        }
+      }
+
+      else if ( scaledStem < cf2_intToFixed( x4 ) )
+      {
+      Try_x4:
+        {
+          FT_Int  xdelta = x4 - x3;
+          FT_Int  ydelta = y4 - y3;
+          FT_Int  x      = stemWidthPer1000 -
+                             FT_DivFix( cf2_intToFixed( x3 ), ppem );
+
+
+          if ( !xdelta )
+            goto Use_y4;
+
+          *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                            FT_DivFix( cf2_intToFixed( y3 ), ppem );
+        }
+      }
+
+      else
+      {
+      Use_y4:
+        *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
+      }
 
       /* use half the amount on each side and convert back to true */
       /* character space                                           */
@@ -157,7 +247,8 @@
 
     /* if a CID fontDict has changed, we need to recompute some cached */
     /* data                                                            */
-    needExtraSetup = font->lastSubfont != cf2_getSubfont( decoder );
+    needExtraSetup =
+      (FT_Bool)( 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 */
@@ -170,7 +261,7 @@
     }
 
     /* copy hinted flag on each call */
-    font->hinted = font->renderingFlags & CF2_FlagsHinted;
+    font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
 
     /* determine if transform has changed;       */
     /* include Fontmatrix but ignore translation */
@@ -204,7 +295,8 @@
      */
     if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
     {
-      font->stemDarkened = font->renderingFlags & CF2_FlagsDarkened;
+      font->stemDarkened =
+        (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
 
       /* blue zones depend on darkened flag */
       needExtraSetup = TRUE;
@@ -266,7 +358,8 @@
                               font->stdVW,
                               &font->darkenX,
                               boldenX,
-                              FALSE );
+                              FALSE,
+                              font->darkenParams );
       }
       else
         cf2_computeDarkening( emRatio,
@@ -274,7 +367,8 @@
                               font->stdVW,
                               &font->darkenX,
                               0,
-                              font->stemDarkened );
+                              font->stemDarkened,
+                              font->darkenParams );
 
 #if 0
       /* since hstem is measured in the y-direction, we use the `d' member */
@@ -301,7 +395,8 @@
                             font->stdHW,
                             &font->darkenY,
                             boldenY,
-                            font->stemDarkened );
+                            font->stemDarkened,
+                            font->darkenParams );
 
       if ( font->darkenX != 0 || font->darkenY != 0 )
         font->darkened = TRUE;
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
index f9dd1bb..d8860ce 100644
--- a/src/cff/cf2font.h
+++ b/src/cff/cf2font.h
@@ -85,6 +85,8 @@
                              /* i.e. darkenX != 0 || darkenY != 0      */
     FT_Bool  stemDarkened;
 
+    FT_Int  darkenParams[8];              /* 1000 unit character space */
+
     /* 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 */
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index c09a024..4abbc9d 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -344,6 +344,15 @@
       if ( scaled && !driver->no_stem_darkening )
         font->renderingFlags |= CF2_FlagsDarkened;
 
+      font->darkenParams[0] = driver->darken_params[0];
+      font->darkenParams[1] = driver->darken_params[1];
+      font->darkenParams[2] = driver->darken_params[2];
+      font->darkenParams[3] = driver->darken_params[3];
+      font->darkenParams[4] = driver->darken_params[4];
+      font->darkenParams[5] = driver->darken_params[5];
+      font->darkenParams[6] = driver->darken_params[6];
+      font->darkenParams[7] = driver->darken_params[7];
+
       /* now get an outline for this glyph;      */
       /* also get units per em to validate scale */
       font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
index 1666e4f..5f44161 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -217,52 +217,52 @@
   FT_LOCAL_DEF( FT_Bool )
   cf2_hint_isValid( const CF2_Hint  hint )
   {
-    return hint->flags != 0;
+    return (FT_Bool)( hint->flags != 0 );
   }
 
 
   static FT_Bool
   cf2_hint_isPair( const CF2_Hint  hint )
   {
-    return ( hint->flags                      &
-             ( CF2_PairBottom | CF2_PairTop ) ) != 0;
+    return (FT_Bool)( ( hint->flags                      &
+                        ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
   }
 
 
   static FT_Bool
   cf2_hint_isPairTop( const CF2_Hint  hint )
   {
-    return ( hint->flags & CF2_PairTop ) != 0;
+    return (FT_Bool)( ( 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;
+    return (FT_Bool)( ( 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;
+    return (FT_Bool)( ( hint->flags                          &
+                        ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
   }
 
 
   static FT_Bool
   cf2_hint_isLocked( const CF2_Hint  hint )
   {
-    return ( hint->flags & CF2_Locked ) != 0;
+    return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
   }
 
 
   static FT_Bool
   cf2_hint_isSynthetic( const CF2_Hint  hint )
   {
-    return ( hint->flags & CF2_Synthetic ) != 0;
+    return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
   }
 
 
@@ -462,7 +462,8 @@
                  hintmap->edge[i].dsCoord + moveDown - downMinCounter )
           {
             move     = moveDown;
-            saveEdge = moveUp < -moveDown;  /* true if non-optimum move */
+            /* true if non-optimum move */
+            saveEdge = (FT_Bool)( moveUp < -moveDown );
           }
           else
           {
@@ -595,22 +596,31 @@
     indexInsert = 0;
     for ( ; indexInsert < hintmap->count; indexInsert++ )
     {
-      if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord )
+      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.
+     * Discard any hints that overlap in character space.  Most often, this
+     * is while building the initial map, where captured hints from all
+     * zones are combined.  Define overlap to include hints that `touch'
+     * (overlap zero).  Hiragino Sans/Gothic fonts have numerous hints that
+     * touch.  Some fonts have non-ideographic glyphs that overlap our
+     * synthetic hints.
+     *
+     * Overlap also occurs when darkening stem hints that are close.
      *
      */
     if ( indexInsert < hintmap->count )
     {
-      /* we are inserting before an existing edge:              */
+      /* we are inserting before an existing edge:    */
+      /* verify that an existing edge is not the same */
+      if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
+        return; /* ignore overlapping stem hint */
+
       /* verify that a new pair does not straddle the next edge */
-      if ( isPair                                                       &&
-           hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord )
+      if ( isPair                                                        &&
+           hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
         return; /* ignore overlapping stem hint */
 
       /* verify that we are not inserting between paired edges */
@@ -644,8 +654,27 @@
                                                   firstHintEdge->csCoord );
     }
 
-    /* discard any hints that overlap in device space; this can occur */
-    /* because locked hints have been moved to align with blue zones  */
+    /*
+     * Discard any hints that overlap in device space; this can occur
+     * because locked hints have been moved to align with blue zones.
+     *
+     * TODO: Although we might correct this later during adjustment, we
+     * don't currently have a way to delete a conflicting hint once it has
+     * been inserted.  See v2.030 MinionPro-Regular, 12 ppem darkened,
+     * initial hint map for second path, glyph 945 (the perispomeni (tilde)
+     * in U+1F6E, Greek omega with psili and perispomeni).  Darkening is
+     * 25.  Pair 667,747 initially conflicts in design space with top edge
+     * 660.  This is because 667 maps to 7.87, and the top edge was
+     * captured by a zone at 8.0.  The pair is later successfully inserted
+     * in a zone without the top edge.  In this zone it is adjusted to 8.0,
+     * and no longer conflicts with the top edge in design space.  This
+     * means it can be included in yet a later zone which does have the top
+     * edge hint.  This produces a small mismatch between the first and
+     * last points of this path, even though the hint masks are the same.
+     * The density map difference is tiny (1/256).
+     *
+     */
+
     if ( indexInsert > 0 )
     {
       /* we are inserting after an existing edge */
@@ -1034,6 +1063,7 @@
 
     glyphpath->moveIsPending = TRUE;
     glyphpath->pathIsOpen    = FALSE;
+    glyphpath->pathIsClosing = FALSE;
     glyphpath->elemIsQueued  = FALSE;
   }
 
@@ -1174,12 +1204,16 @@
   /*
    * 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.
+   * cached element may be adjusted to an intersection point or we may
+   * synthesize a connecting line to the current element.  If we are
+   * closing a subpath, we may also generate a connecting line to the start
+   * point.
+   *
+   * This is where Character Space (CS) is converted to Device Space (DS)
+   * using a hint map.  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:
@@ -1249,16 +1283,32 @@
       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 );
+      if ( close )
+      {
+        /* use first hint map if closing */
+        cf2_glyphpath_hintPoint( glyphpath,
+                                 &glyphpath->firstHintMap,
+                                 &params.pt1,
+                                 glyphpath->prevElemP1.x,
+                                 glyphpath->prevElemP1.y );
+      }
+      else
+      {
+        cf2_glyphpath_hintPoint( glyphpath,
+                                 hintmap,
+                                 &params.pt1,
+                                 glyphpath->prevElemP1.x,
+                                 glyphpath->prevElemP1.y );
+      }
 
-      glyphpath->currentDS = params.pt1;
+      /* output only non-zero length lines */
+      if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
+      {
+        glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
 
+        glyphpath->currentDS = params.pt1;
+      }
       break;
 
     case CF2_PathOpCubeTo:
@@ -1295,11 +1345,24 @@
       /* 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 ( close )
+      {
+        /* if we are closing the subpath, then nextP0 is in the first     */
+        /* hint zone                                                      */
+        cf2_glyphpath_hintPoint( glyphpath,
+                                 &glyphpath->firstHintMap,
+                                 &params.pt1,
+                                 nextP0->x,
+                                 nextP0->y );
+      }
+      else
+      {
+        cf2_glyphpath_hintPoint( glyphpath,
+                                 hintmap,
+                                 &params.pt1,
+                                 nextP0->x,
+                                 nextP0->y );
+      }
 
       if ( params.pt1.x != glyphpath->currentDS.x ||
            params.pt1.y != glyphpath->currentDS.y )
@@ -1510,6 +1573,16 @@
   }
 
 
+  /*
+   * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are
+   * called by the interpreter with Character Space (CS) coordinates.  Each
+   * path element is placed into a queue of length one to await the
+   * calculation of the following element.  At that time, the darkening
+   * offset of the following element is known and joins can be computed,
+   * including possible modification of this element, before mapping to
+   * Device Space (DS) and passing it on to the outline consumer.
+   *
+   */
   FT_LOCAL_DEF( void )
   cf2_glyphpath_moveTo( CF2_GlyphPath  glyphpath,
                         CF2_Fixed      x,
@@ -1547,10 +1620,46 @@
   {
     CF2_Fixed  xOffset, yOffset;
     FT_Vector  P0, P1;
+    FT_Bool    newHintMap;
 
+    /*
+     * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
+     * In case this is a synthesized closing line, any new hints should be
+     * delayed until this path is closed (`cf2_hintmask_isNew' will be
+     * called again before the next line or curve).
+     */
 
-    /* can't compute offset of zero length line, so ignore them */
-    if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y )
+    /* true if new hint map not on close */
+    newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
+                 !glyphpath->pathIsClosing;
+
+    /*
+     * Zero-length lines may occur in the charstring.  Because we cannot
+     * compute darkening offsets or intersections from zero-length lines,
+     * it is best to remove them and avoid artifacts.  However, zero-length
+     * lines in CS at the start of a new hint map can generate non-zero
+     * lines in DS due to hint substitution.  We detect a change in hint
+     * map here and pass those zero-length lines along.
+     */
+
+    /*
+     * Note: Find explicitly closed paths here with a conditional
+     *       breakpoint using
+     *
+     *         !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
+     *
+     */
+
+    if ( glyphpath->currentCS.x == x &&
+         glyphpath->currentCS.y == y &&
+         !newHintMap                 )
+      /*
+       * Ignore zero-length lines in CS where the hint map is the same
+       * because the line in DS will also be zero length.
+       *
+       * Ignore zero-length lines when we synthesize a closing line because
+       * the close will be handled in cf2_glyphPath_pushPrevElem.
+       */
       return;
 
     cf2_glyphpath_computeOffset( glyphpath,
@@ -1596,7 +1705,7 @@
     glyphpath->prevElemP1   = P1;
 
     /* update current map */
-    if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
+    if ( newHintMap )
       cf2_hintmap_build( &glyphpath->hintMap,
                          glyphpath->hStemHintArray,
                          glyphpath->vStemHintArray,
@@ -1702,29 +1811,29 @@
   {
     if ( glyphpath->pathIsOpen )
     {
-      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) );
+      /*
+       * A closing line in Character Space line is always generated below
+       * with `cf2_glyphPath_lineTo'.  It may be ignored later if it turns
+       * out to be zero length in Device Space.
+       */
+      glyphpath->pathIsClosing = TRUE;
 
-      /* 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 );
+      /* empty the final element from the queue and close the path */
+      if ( glyphpath->elemIsQueued )
+        cf2_glyphpath_pushPrevElem( glyphpath,
+                                    &glyphpath->hintMap,
+                                    &glyphpath->offsetStart0,
+                                    glyphpath->offsetStart1,
+                                    TRUE );
 
       /* reset state machine */
       glyphpath->moveIsPending = TRUE;
       glyphpath->pathIsOpen    = FALSE;
+      glyphpath->pathIsClosing = FALSE;
       glyphpath->elemIsQueued  = FALSE;
     }
   }
diff --git a/src/cff/cf2hints.h b/src/cff/cf2hints.h
index c4fa922..f25d91b 100644
--- a/src/cff/cf2hints.h
+++ b/src/cff/cf2hints.h
@@ -204,6 +204,7 @@
 #endif
 
     FT_Bool  pathIsOpen;     /* true after MoveTo                     */
+    FT_Bool  pathIsClosing;  /* true when synthesizing closepath line */
     FT_Bool  darken;         /* true if stem darkening                */
     FT_Bool  moveIsPending;  /* true between MoveTo and offset MoveTo */
 
@@ -229,7 +230,8 @@
     FT_Vector  currentCS;
     /* current point, device space */
     FT_Vector  currentDS;
-    FT_Vector  start;         /* start point of subpath */
+    /* start point of subpath, character space */
+    FT_Vector  start;
 
     /* the following members constitute the `queue' of one element */
     FT_Bool  elemIsQueued;
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
index 5b73e60..5610917 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -287,7 +287,7 @@
   {
     CF2_UInt  i;
     CF2_UInt  count       = cf2_stack_count( opStack );
-    FT_Bool   hasWidthArg = count & 1;
+    FT_Bool   hasWidthArg = (FT_Bool)( count & 1 );
 
     /* variable accumulates delta values from operand stack */
     CF2_Fixed  position = hintOffset;
@@ -357,8 +357,8 @@
 
     if ( doConditionalLastRead )
     {
-      FT_Bool    lastIsX = cf2_fixedAbs( vals[10] - *curX ) >
-                             cf2_fixedAbs( vals[11] - *curY );
+      FT_Bool    lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) >
+                                        cf2_fixedAbs( vals[11] - *curY ) );
       CF2_Fixed  lastVal = cf2_stack_getReal( opStack, index );
 
 
diff --git a/src/cff/cf2read.c b/src/cff/cf2read.c
index cb671ec..2b429e3 100644
--- a/src/cff/cf2read.c
+++ b/src/cff/cf2read.c
@@ -105,7 +105,7 @@
   FT_LOCAL_DEF( FT_Bool )
   cf2_buf_isEnd( CF2_Buffer  buf )
   {
-    return buf->ptr >= buf->end;
+    return (FT_Bool)( buf->ptr >= buf->end );
   }
 
 
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index c8ca96b..dde7d44 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -164,6 +164,8 @@
     if ( !slot )
       return FT_THROW( Invalid_Slot_Handle );
 
+    FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
+
     /* check whether we want a scaled outline or bitmap */
     if ( !size )
       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
@@ -586,7 +588,38 @@
     CFF_Driver  driver = (CFF_Driver)module;
 
 
-    if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = (FT_Int*)value;
+
+      FT_Int  x1 = darken_params[0];
+      FT_Int  y1 = darken_params[1];
+      FT_Int  x2 = darken_params[2];
+      FT_Int  y2 = darken_params[3];
+      FT_Int  x3 = darken_params[4];
+      FT_Int  y3 = darken_params[5];
+      FT_Int  x4 = darken_params[6];
+      FT_Int  y4 = darken_params[7];
+
+
+      if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
+           y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
+           x1 > x2  || x2 > x3  || x3 > x4              ||
+           y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+        return FT_THROW( Invalid_Argument );
+
+      driver->darken_params[0] = x1;
+      driver->darken_params[1] = y1;
+      driver->darken_params[2] = x2;
+      driver->darken_params[3] = y2;
+      driver->darken_params[4] = x3;
+      driver->darken_params[5] = y3;
+      driver->darken_params[6] = x4;
+      driver->darken_params[7] = y4;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
     {
       FT_UInt*  hinting_engine = (FT_UInt*)value;
 
@@ -624,13 +657,28 @@
     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" ) )
+    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
     {
-      FT_UInt*  val = (FT_UInt*)value;
+      FT_Int*  darken_params = driver->darken_params;
+      FT_Int*  val           = (FT_Int*)value;
+
+
+      val[0] = darken_params[0];
+      val[1] = darken_params[1];
+      val[2] = darken_params[2];
+      val[3] = darken_params[3];
+      val[4] = darken_params[4];
+      val[5] = darken_params[5];
+      val[6] = darken_params[6];
+      val[7] = darken_params[7];
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    {
+      FT_UInt   hinting_engine    = driver->hinting_engine;
+      FT_UInt*  val               = (FT_UInt*)value;
 
 
       *val = hinting_engine;
@@ -639,7 +687,8 @@
     }
     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
     {
-      FT_Bool*  val = (FT_Bool*)value;
+      FT_Bool   no_stem_darkening = driver->no_stem_darkening;
+      FT_Bool*  val               = (FT_Bool*)value;
 
 
       *val = no_stem_darkening;
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 1904ca0..c8e9f91 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -434,7 +434,7 @@
         goto Exit;
       }
 
-      FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
+      FT_TRACE3(( "  in subfont %d:\n", fd_index ));
 
       sub = cff->subfonts[fd_index];
 
@@ -447,10 +447,6 @@
         builder->hints_globals = (void *)internal->subfonts[fd_index];
       }
     }
-#ifdef FT_DEBUG_LEVEL_TRACE
-    else
-      FT_TRACE3(( "glyph index %d:\n", glyph_index ));
-#endif
 
     decoder->num_locals    = sub->local_subrs_index.count;
     decoder->locals        = sub->local_subrs;
@@ -2849,7 +2845,16 @@
         /* as a consequence, glyphs larger than 2000ppem get rejected */
         if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
         {
-          /* XXX to be implemented */
+          /* this time, we retry unhinted and scale up the glyph later on */
+          /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
+          /* 0x400 for both `x_scale' and `y_scale' in this case)         */
+          hinting       = FALSE;
+          force_scaling = TRUE;
+          glyph->hint   = hinting;
+
+          error = cf2_decoder_parse_charstrings( &decoder,
+                                                 charstring,
+                                                 charstring_len );
         }
       }
 
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 64b4971..ff271f3 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -414,7 +414,7 @@
       cur_offset = idx->offsets[0] - 1;
 
       /* sanity check */
-      if ( cur_offset >= idx->data_size )
+      if ( cur_offset != 0 )
       {
         FT_TRACE0(( "cff_index_get_pointers:"
                     " invalid first offset value %d set to zero\n",
@@ -432,11 +432,11 @@
         FT_ULong  next_offset = idx->offsets[n] - 1;
 
 
-        /* empty slot + two sanity checks for invalid offset tables */
-        if ( next_offset == 0                                    ||
-             next_offset < cur_offset                            ||
-             ( next_offset >= idx->data_size && n < idx->count ) )
+        /* two sanity checks for invalid offset tables */
+        if ( next_offset < cur_offset )
           next_offset = cur_offset;
+        else if ( next_offset > idx->data_size )
+          next_offset = idx->data_size;
 
         if ( !pool )
           t[n] = org_bytes + next_offset;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index dd750d1..29c3691 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -1055,7 +1055,7 @@
     CFF_Driver  driver = (CFF_Driver)module;
 
 
-    /* set default property values */
+    /* set default property values, cf `ftcffdrv.h' */
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
     driver->hinting_engine    = FT_CFF_HINTING_FREETYPE;
 #else
@@ -1063,6 +1063,15 @@
 #endif
     driver->no_stem_darkening = FALSE;
 
+    driver->darken_params[0] =  500;
+    driver->darken_params[1] =  400;
+    driver->darken_params[2] = 1000;
+    driver->darken_params[3] =  275;
+    driver->darken_params[4] = 1667;
+    driver->darken_params[5] =  275;
+    driver->darken_params[6] = 2333;
+    driver->darken_params[7] =    0;
+
     return FT_Err_Ok;
   }
 
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index b375c20..dfbf9a9 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -121,6 +121,8 @@
     FT_UInt  hinting_engine;
     FT_Bool  no_stem_darkening;
 
+    FT_Int  darken_params[8];
+
   } CFF_DriverRec;
 
 
diff --git a/src/gzip/adler32.c b/src/gzip/adler32.c
new file mode 100644
index 0000000..c53f9dd
--- /dev/null
+++ b/src/gzip/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+ZEXPORT(uLong) adler32( /* adler, buf, len) */
+    uLong adler,
+    const Bytef *buf,
+    uInt len )
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+            s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
new file mode 100644
index 0000000..2c60b6c
--- /dev/null
+++ b/src/gzip/ftgzip.c
@@ -0,0 +1,778 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftgzip.c                                                               */
+/*                                                                         */
+/*    FreeType support for .gz compressed files.                           */
+/*                                                                         */
+/*  This optional component relies on zlib.  It should mainly be used to   */
+/*  parse compressed PCF fonts, as found with many X11 server              */
+/*  distributions.                                                         */
+/*                                                                         */
+/*  Copyright 2002-2006, 2009-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_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_GZIP_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef  FT_ERR_PREFIX
+#define FT_ERR_PREFIX  Gzip_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Gzip
+
+#include FT_ERRORS_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "gzip code does not support PIC yet"
+#endif
+
+#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
+
+#include <zlib.h>
+
+#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+ /* In this case, we include our own modified sources of the ZLib    */
+ /* within the "ftgzip" component.  The modifications were necessary */
+ /* to #include all files without conflicts, as well as preventing   */
+ /* the definition of "extern" functions that may cause linking      */
+ /* conflicts when a program is linked with both FreeType and the    */
+ /* original ZLib.                                                   */
+
+#define NO_DUMMY_DECL
+#ifndef USE_ZLIB_ZCALLOC
+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */
+#endif
+
+#include "zlib.h"
+
+#undef  SLOW
+#define SLOW  1  /* we can't use asm-optimized sources here! */
+
+#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: zlib is non-FreeType     */
+  /* code.                                                   */
+#pragma warning( push )
+#pragma warning( disable : 4244 )
+#endif /* _MSC_VER */
+
+  /* Urgh.  `inflate_mask' must not be declared twice -- C++ doesn't like
+     this.  We temporarily disable it and load all necessary header files. */
+#define NO_INFLATE_MASK
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#undef  NO_INFLATE_MASK
+
+  /* infutil.c must be included before infcodes.c */
+#include "zutil.c"
+#include "inftrees.c"
+#include "infutil.c"
+#include "infcodes.c"
+#include "infblock.c"
+#include "inflate.c"
+#include "adler32.c"
+
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
+#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/*****                                                                 *****/
+/*****            Z L I B   M E M O R Y   M A N A G E M E N T          *****/
+/*****                                                                 *****/
+/***************************************************************************/
+/***************************************************************************/
+
+  /* it is better to use FreeType memory routines instead of raw
+     'malloc/free' */
+
+  static voidpf
+  ft_gzip_alloc( FT_Memory  memory,
+                 uInt       items,
+                 uInt       size )
+  {
+    FT_ULong    sz = (FT_ULong)size * items;
+    FT_Error    error;
+    FT_Pointer  p  = NULL;
+
+
+    (void)FT_ALLOC( p, sz );
+    return p;
+  }
+
+
+  static void
+  ft_gzip_free( FT_Memory  memory,
+                voidpf     address )
+  {
+    FT_MEM_FREE( address );
+  }
+
+
+#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC )
+
+  local voidpf
+  zcalloc ( voidpf    opaque,
+            unsigned  items,
+            unsigned  size )
+  {
+    return ft_gzip_alloc( (FT_Memory)opaque, items, size );
+  }
+
+  local void
+  zcfree( voidpf  opaque,
+          voidpf  ptr )
+  {
+    ft_gzip_free( (FT_Memory)opaque, ptr );
+  }
+
+#endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/*****                                                                 *****/
+/*****               Z L I B   F I L E   D E S C R I P T O R           *****/
+/*****                                                                 *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_GZIP_BUFFER_SIZE  4096
+
+  typedef struct  FT_GZipFileRec_
+  {
+    FT_Stream  source;         /* parent/source stream        */
+    FT_Stream  stream;         /* embedding stream            */
+    FT_Memory  memory;         /* memory allocator            */
+    z_stream   zstream;        /* zlib input stream           */
+
+    FT_ULong   start;          /* starting position, after .gz header */
+    FT_Byte    input[FT_GZIP_BUFFER_SIZE];   /* input read buffer  */
+
+    FT_Byte    buffer[FT_GZIP_BUFFER_SIZE];  /* output buffer      */
+    FT_ULong   pos;                          /* position in output */
+    FT_Byte*   cursor;
+    FT_Byte*   limit;
+
+  } FT_GZipFileRec, *FT_GZipFile;
+
+
+  /* gzip flag byte */
+#define FT_GZIP_ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define FT_GZIP_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define FT_GZIP_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define FT_GZIP_ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define FT_GZIP_COMMENT      0x10 /* bit 4 set: file comment present */
+#define FT_GZIP_RESERVED     0xE0 /* bits 5..7: reserved */
+
+
+  /* check and skip .gz header - we don't support `transparent' compression */
+  static FT_Error
+  ft_gzip_check_header( FT_Stream  stream )
+  {
+    FT_Error  error;
+    FT_Byte   head[4];
+
+
+    if ( FT_STREAM_SEEK( 0 )       ||
+         FT_STREAM_READ( head, 4 ) )
+      goto Exit;
+
+    /* head[0] && head[1] are the magic numbers;    */
+    /* head[2] is the method, and head[3] the flags */
+    if ( head[0] != 0x1f              ||
+         head[1] != 0x8b              ||
+         head[2] != Z_DEFLATED        ||
+        (head[3] & FT_GZIP_RESERVED)  )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* skip time, xflags and os code */
+    (void)FT_STREAM_SKIP( 6 );
+
+    /* skip the extra field */
+    if ( head[3] & FT_GZIP_EXTRA_FIELD )
+    {
+      FT_UInt  len;
+
+
+      if ( FT_READ_USHORT_LE( len ) ||
+           FT_STREAM_SKIP( len )    )
+        goto Exit;
+    }
+
+    /* skip original file name */
+    if ( head[3] & FT_GZIP_ORIG_NAME )
+      for (;;)
+      {
+        FT_UInt  c;
+
+
+        if ( FT_READ_BYTE( c ) )
+          goto Exit;
+
+        if ( c == 0 )
+          break;
+      }
+
+    /* skip .gz comment */
+    if ( head[3] & FT_GZIP_COMMENT )
+      for (;;)
+      {
+        FT_UInt  c;
+
+
+        if ( FT_READ_BYTE( c ) )
+          goto Exit;
+
+        if ( c == 0 )
+          break;
+      }
+
+    /* skip CRC */
+    if ( head[3] & FT_GZIP_HEAD_CRC )
+      if ( FT_STREAM_SKIP( 2 ) )
+        goto Exit;
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  ft_gzip_file_init( FT_GZipFile  zip,
+                     FT_Stream    stream,
+                     FT_Stream    source )
+  {
+    z_stream*  zstream = &zip->zstream;
+    FT_Error   error   = FT_Err_Ok;
+
+
+    zip->stream = stream;
+    zip->source = source;
+    zip->memory = stream->memory;
+
+    zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
+    zip->cursor = zip->limit;
+    zip->pos    = 0;
+
+    /* check and skip .gz header */
+    {
+      stream = source;
+
+      error = ft_gzip_check_header( stream );
+      if ( error )
+        goto Exit;
+
+      zip->start = FT_STREAM_POS();
+    }
+
+    /* initialize zlib -- there is no zlib header in the compressed stream */
+    zstream->zalloc = (alloc_func)ft_gzip_alloc;
+    zstream->zfree  = (free_func) ft_gzip_free;
+    zstream->opaque = stream->memory;
+
+    zstream->avail_in = 0;
+    zstream->next_in  = zip->buffer;
+
+    if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
+         zstream->next_in == NULL                     )
+      error = FT_THROW( Invalid_File_Format );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  ft_gzip_file_done( FT_GZipFile  zip )
+  {
+    z_stream*  zstream = &zip->zstream;
+
+
+    inflateEnd( zstream );
+
+    /* clear the rest */
+    zstream->zalloc    = NULL;
+    zstream->zfree     = NULL;
+    zstream->opaque    = NULL;
+    zstream->next_in   = NULL;
+    zstream->next_out  = NULL;
+    zstream->avail_in  = 0;
+    zstream->avail_out = 0;
+
+    zip->memory = NULL;
+    zip->source = NULL;
+    zip->stream = NULL;
+  }
+
+
+  static FT_Error
+  ft_gzip_file_reset( FT_GZipFile  zip )
+  {
+    FT_Stream  stream = zip->source;
+    FT_Error   error;
+
+
+    if ( !FT_STREAM_SEEK( zip->start ) )
+    {
+      z_stream*  zstream = &zip->zstream;
+
+
+      inflateReset( zstream );
+
+      zstream->avail_in  = 0;
+      zstream->next_in   = zip->input;
+      zstream->avail_out = 0;
+      zstream->next_out  = zip->buffer;
+
+      zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
+      zip->cursor = zip->limit;
+      zip->pos    = 0;
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  ft_gzip_file_fill_input( FT_GZipFile  zip )
+  {
+    z_stream*  zstream = &zip->zstream;
+    FT_Stream  stream  = zip->source;
+    FT_ULong   size;
+
+
+    if ( stream->read )
+    {
+      size = stream->read( stream, stream->pos, zip->input,
+                           FT_GZIP_BUFFER_SIZE );
+      if ( size == 0 )
+        return FT_THROW( Invalid_Stream_Operation );
+    }
+    else
+    {
+      size = stream->size - stream->pos;
+      if ( size > FT_GZIP_BUFFER_SIZE )
+        size = FT_GZIP_BUFFER_SIZE;
+
+      if ( size == 0 )
+        return FT_THROW( Invalid_Stream_Operation );
+
+      FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
+    }
+    stream->pos += size;
+
+    zstream->next_in  = zip->input;
+    zstream->avail_in = size;
+
+    return FT_Err_Ok;
+  }
+
+
+  static FT_Error
+  ft_gzip_file_fill_output( FT_GZipFile  zip )
+  {
+    z_stream*  zstream = &zip->zstream;
+    FT_Error   error   = FT_Err_Ok;
+
+
+    zip->cursor        = zip->buffer;
+    zstream->next_out  = zip->cursor;
+    zstream->avail_out = FT_GZIP_BUFFER_SIZE;
+
+    while ( zstream->avail_out > 0 )
+    {
+      int  err;
+
+
+      if ( zstream->avail_in == 0 )
+      {
+        error = ft_gzip_file_fill_input( zip );
+        if ( error )
+          break;
+      }
+
+      err = inflate( zstream, Z_NO_FLUSH );
+
+      if ( err == Z_STREAM_END )
+      {
+        zip->limit = zstream->next_out;
+        if ( zip->limit == zip->cursor )
+          error = FT_THROW( Invalid_Stream_Operation );
+        break;
+      }
+      else if ( err != Z_OK )
+      {
+        error = FT_THROW( Invalid_Stream_Operation );
+        break;
+      }
+    }
+
+    return error;
+  }
+
+
+  /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */
+  static FT_Error
+  ft_gzip_file_skip_output( FT_GZipFile  zip,
+                            FT_ULong     count )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  delta;
+
+
+    for (;;)
+    {
+      delta = (FT_ULong)( zip->limit - zip->cursor );
+      if ( delta >= count )
+        delta = count;
+
+      zip->cursor += delta;
+      zip->pos    += delta;
+
+      count -= delta;
+      if ( count == 0 )
+        break;
+
+      error = ft_gzip_file_fill_output( zip );
+      if ( error )
+        break;
+    }
+
+    return error;
+  }
+
+
+  static FT_ULong
+  ft_gzip_file_io( FT_GZipFile  zip,
+                   FT_ULong     pos,
+                   FT_Byte*     buffer,
+                   FT_ULong     count )
+  {
+    FT_ULong  result = 0;
+    FT_Error  error;
+
+
+    /* Reset inflate stream if we're seeking backwards.        */
+    /* Yes, that is not too efficient, but it saves memory :-) */
+    if ( pos < zip->pos )
+    {
+      error = ft_gzip_file_reset( zip );
+      if ( error )
+        goto Exit;
+    }
+
+    /* skip unwanted bytes */
+    if ( pos > zip->pos )
+    {
+      error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+      if ( error )
+        goto Exit;
+    }
+
+    if ( count == 0 )
+      goto Exit;
+
+    /* now read the data */
+    for (;;)
+    {
+      FT_ULong  delta;
+
+
+      delta = (FT_ULong)( zip->limit - zip->cursor );
+      if ( delta >= count )
+        delta = count;
+
+      FT_MEM_COPY( buffer, zip->cursor, delta );
+      buffer      += delta;
+      result      += delta;
+      zip->cursor += delta;
+      zip->pos    += delta;
+
+      count -= delta;
+      if ( count == 0 )
+        break;
+
+      error = ft_gzip_file_fill_output( zip );
+      if ( error )
+        break;
+    }
+
+  Exit:
+    return result;
+  }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/*****                                                                 *****/
+/*****               G Z   E M B E D D I N G   S T R E A M             *****/
+/*****                                                                 *****/
+/***************************************************************************/
+/***************************************************************************/
+
+  static void
+  ft_gzip_stream_close( FT_Stream  stream )
+  {
+    FT_GZipFile  zip    = (FT_GZipFile)stream->descriptor.pointer;
+    FT_Memory    memory = stream->memory;
+
+
+    if ( zip )
+    {
+      /* finalize gzip file descriptor */
+      ft_gzip_file_done( zip );
+
+      FT_FREE( zip );
+
+      stream->descriptor.pointer = NULL;
+    }
+  }
+
+
+  static FT_ULong
+  ft_gzip_stream_io( FT_Stream  stream,
+                     FT_ULong   pos,
+                     FT_Byte*   buffer,
+                     FT_ULong   count )
+  {
+    FT_GZipFile  zip = (FT_GZipFile)stream->descriptor.pointer;
+
+
+    return ft_gzip_file_io( zip, pos, buffer, count );
+  }
+
+
+  static FT_ULong
+  ft_gzip_get_uncompressed_size( FT_Stream  stream )
+  {
+    FT_Error  error;
+    FT_ULong  old_pos;
+    FT_ULong  result = 0;
+
+
+    old_pos = stream->pos;
+    if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
+    {
+      result = FT_Stream_ReadULong( stream, &error );
+      if ( error )
+        result = 0;
+
+      (void)FT_Stream_Seek( stream, old_pos );
+    }
+
+    return result;
+  }
+
+
+  /* documentation is in ftgzip.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Stream_OpenGzip( FT_Stream  stream,
+                      FT_Stream  source )
+  {
+    FT_Error     error;
+    FT_Memory    memory = source->memory;
+    FT_GZipFile  zip = NULL;
+
+
+    /*
+     *  check the header right now; this prevents allocating un-necessary
+     *  objects when we don't need them
+     */
+    error = ft_gzip_check_header( source );
+    if ( error )
+      goto Exit;
+
+    FT_ZERO( stream );
+    stream->memory = memory;
+
+    if ( !FT_QNEW( zip ) )
+    {
+      error = ft_gzip_file_init( zip, stream, source );
+      if ( error )
+      {
+        FT_FREE( zip );
+        goto Exit;
+      }
+
+      stream->descriptor.pointer = zip;
+    }
+
+    /*
+     *  We use the following trick to try to dramatically improve the
+     *  performance while dealing with small files.  If the original stream
+     *  size is less than a certain threshold, we try to load the whole font
+     *  file into memory.  This saves us from using the 32KB buffer needed
+     *  to inflate the file, plus the two 4KB intermediate input/output
+     *  buffers used in the `FT_GZipFile' structure.
+     */
+    {
+      FT_ULong  zip_size = ft_gzip_get_uncompressed_size( source );
+
+
+      if ( zip_size != 0 && zip_size < 40 * 1024 )
+      {
+        FT_Byte*  zip_buff = NULL;
+
+
+        if ( !FT_ALLOC( zip_buff, zip_size ) )
+        {
+          FT_ULong  count;
+
+
+          count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
+          if ( count == zip_size )
+          {
+            ft_gzip_file_done( zip );
+            FT_FREE( zip );
+
+            stream->descriptor.pointer = NULL;
+
+            stream->size  = zip_size;
+            stream->pos   = 0;
+            stream->base  = zip_buff;
+            stream->read  = NULL;
+            stream->close = ft_gzip_stream_close;
+
+            goto Exit;
+          }
+
+          ft_gzip_file_io( zip, 0, NULL, 0 );
+          FT_FREE( zip_buff );
+        }
+        error = FT_Err_Ok;
+      }
+    }
+
+    stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
+    stream->pos   = 0;
+    stream->base  = 0;
+    stream->read  = ft_gzip_stream_io;
+    stream->close = ft_gzip_stream_close;
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftgzip.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Gzip_Uncompress( FT_Memory       memory,
+                      FT_Byte*        output,
+                      FT_ULong*       output_len,
+                      const FT_Byte*  input,
+                      FT_ULong        input_len )
+  {
+    z_stream  stream;
+    int       err;
+
+
+    /* this function is modeled after zlib's `uncompress' function */
+
+    stream.next_in  = (Bytef*)input;
+    stream.avail_in = (uInt)input_len;
+
+    stream.next_out  = output;
+    stream.avail_out = (uInt)*output_len;
+
+    stream.zalloc = (alloc_func)ft_gzip_alloc;
+    stream.zfree  = (free_func) ft_gzip_free;
+    stream.opaque = memory;
+
+    err = inflateInit2( &stream, MAX_WBITS );
+    if ( err != Z_OK )
+      return FT_THROW( Invalid_Argument );
+
+    err = inflate( &stream, Z_FINISH );
+    if ( err != Z_STREAM_END )
+    {
+      inflateEnd( &stream );
+      if ( err == Z_OK )
+        err = Z_BUF_ERROR;
+    }
+    else
+    {
+      *output_len = stream.total_out;
+
+      err = inflateEnd( &stream );
+    }
+
+    if ( err == Z_MEM_ERROR )
+      return FT_THROW( Out_Of_Memory );
+
+    if ( err == Z_BUF_ERROR )
+      return FT_THROW( Array_Too_Large );
+
+    if ( err == Z_DATA_ERROR )
+      return FT_THROW( Invalid_Table );
+
+    return FT_Err_Ok;
+  }
+
+
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Stream_OpenGzip( FT_Stream  stream,
+                      FT_Stream  source )
+  {
+    FT_UNUSED( stream );
+    FT_UNUSED( source );
+
+    return FT_THROW( Unimplemented_Feature );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Gzip_Uncompress( FT_Memory       memory,
+                      FT_Byte*        output,
+                      FT_ULong*       output_len,
+                      const FT_Byte*  input,
+                      FT_ULong        input_len )
+  {
+    FT_UNUSED( memory );
+    FT_UNUSED( output );
+    FT_UNUSED( output_len );
+    FT_UNUSED( input );
+    FT_UNUSED( input_len );
+
+    return FT_THROW( Unimplemented_Feature );
+  }
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+
+/* END */
diff --git a/src/gzip/infblock.c b/src/gzip/infblock.c
new file mode 100644
index 0000000..d6e2dc2
--- /dev/null
+++ b/src/gzip/infblock.c
@@ -0,0 +1,387 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset( /* s, z, c) */
+inflate_blocks_statef *s,
+z_streamp z,
+uLongf *c )
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens);
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+  Tracev((stderr, "inflate:   blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */
+z_streamp z,
+check_func c,
+uInt w )
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->hufts =
+       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+  {
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s->hufts);
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+
+
+local int inflate_blocks( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl,
+                                          (const inflate_huft**)&td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+        {
+          ZFREE(z, s->sub.trees.blens);
+          s->mode = BAD;
+        }
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+          }
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      ZFREE(z, s->sub.trees.blens);
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return 0;
+#endif
+}
+
+
+local int inflate_blocks_free( /* s, z) */
+inflate_blocks_statef *s,
+z_streamp z )
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  ZFREE(z, s->window);
+  ZFREE(z, s->hufts);
+  ZFREE(z, s);
+  Tracev((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+
diff --git a/src/gzip/infblock.h b/src/gzip/infblock.h
new file mode 100644
index 0000000..c2535a1
--- /dev/null
+++ b/src/gzip/infblock.h
@@ -0,0 +1,36 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFBLOCK_H
+#define _INFBLOCK_H
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local  inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+local  int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+local  void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLongf *));                  /* check value on output */
+
+local  int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+#endif /* _INFBLOCK_H */
diff --git a/src/gzip/infcodes.c b/src/gzip/infcodes.c
new file mode 100644
index 0000000..f7bfd58
--- /dev/null
+++ b/src/gzip/infcodes.c
@@ -0,0 +1,250 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */
+uInt bl, uInt bd,
+inflate_huft *tl,
+inflate_huft *td, /* need separate declaration for Borland C++ */
+z_streamp z )
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+local int inflate_codes( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+      f = q - c->sub.copy.dist;
+      while (f < s->window)             /* modulo window size-"while" instead */
+        f += s->end - s->window;        /* of "if" handles invalid distances */
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+local void inflate_codes_free( /* c, z) */
+inflate_codes_statef *c,
+z_streamp z )
+{
+  ZFREE(z, c);
+  Tracev((stderr, "inflate:       codes free\n"));
+}
diff --git a/src/gzip/infcodes.h b/src/gzip/infcodes.h
new file mode 100644
index 0000000..154d7f8
--- /dev/null
+++ b/src/gzip/infcodes.h
@@ -0,0 +1,31 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFCODES_H
+#define _INFCODES_H
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+local int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+local void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
+#endif /* _INFCODES_H */
diff --git a/src/gzip/inffixed.h b/src/gzip/inffixed.h
new file mode 100644
index 0000000..4d4760e
--- /dev/null
+++ b/src/gzip/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local const uInt fixed_bl = 9;
+local const uInt fixed_bd = 5;
+local const inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+local const inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
diff --git a/src/gzip/inflate.c b/src/gzip/inflate.c
new file mode 100644
index 0000000..8877fa3
--- /dev/null
+++ b/src/gzip/inflate.c
@@ -0,0 +1,273 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+#define  DONE  INFLATE_DONE
+#define  BAD   INFLATE_BAD
+
+typedef enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      DICT4,    /* four dictionary check bytes to go */
+      DICT3,    /* three dictionary check bytes to go */
+      DICT2,    /* two dictionary check bytes to go */
+      DICT1,    /* one dictionary check byte to go */
+      DICT0,    /* waiting for inflateSetDictionary */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+ZEXPORT(int) inflateReset( /* z) */
+z_streamp z )
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+ZEXPORT(int) inflateEnd( /* z) */
+z_streamp z )
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  Tracev((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */
+z_streamp z,
+int w,
+const char *version,
+int stream_size )
+{
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  if (z->zalloc == Z_NULL)
+  {
+    z->zalloc = zcalloc;
+    z->opaque = (voidpf)0;
+  }
+  if (z->zfree == Z_NULL) z->zfree = zcfree;
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+
+#undef  NEEDBYTE
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+
+#undef  NEXTBYTE
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+
+ZEXPORT(int) inflate( /* z, f) */
+z_streamp z,
+int f )
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      b = NEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = BLOCKS;
+        break;
+      }
+      z->state->mode = DICT4;
+    case DICT4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = DICT3;
+    case DICT3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = DICT2;
+    case DICT2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = DICT1;
+    case DICT1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = DICT0;
+      return Z_NEED_DICT;
+    case DICT0:
+      z->state->mode = BAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
diff --git a/src/gzip/inftrees.c b/src/gzip/inftrees.c
new file mode 100644
index 0000000..ef53652
--- /dev/null
+++ b/src/gzip/inftrees.c
@@ -0,0 +1,468 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+
+#if 0
+local const char inflate_copyright[] =
+   " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
+#endif
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uIntf *,      /* list of base values for non-simple codes */
+    const uIntf *,      /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uIntf * ));         /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */
+uIntf *b,               /* code lengths in bits (all assumed <= BMAX) */
+uInt n,                 /* number of codes (assumed <= 288) */
+uInt s,                 /* number of simple-valued codes (0..s-1) */
+const uIntf *d,         /* list of base values for non-simple codes */
+const uIntf *e,         /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t,  /* result: starting table */
+uIntf *m,               /* maximum lookup bits, returns actual */
+inflate_huft *hp,       /* space for trees */
+uInt *hn,               /* hufts used in space */
+uIntf *v                /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), or Z_DATA_ERROR if the input is invalid. */
+)
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Make compiler happy */
+  r.base = 0;
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? (uInt)l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_DATA_ERROR;  /* overflow of MANY */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits( /* c, bb, tb, hp, z) */
+uIntf *c,               /* 19 code lengths */
+uIntf *bb,              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb, /* bits tree result */
+inflate_huft *hp,       /* space for trees */
+z_streamp z             /* for messages */
+)
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  ZFREE(z, v);
+  return r;
+}
+
+
+local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */
+uInt nl,                /* number of literal/length codes */
+uInt nd,                /* number of distance codes */
+uIntf *c,               /* that many (total) code lengths */
+uIntf *bl,              /* literal desired/actual bit depth */
+uIntf *bd,              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl, /* literal/length tree result */
+inflate_huft * FAR *td, /* distance tree result */
+inflate_huft *hp,       /* space for trees */
+z_streamp z             /* for messages */
+)
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  /* allocate work area */
+  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#if 0
+    {
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+#endif
+  }
+
+  /* done */
+  ZFREE(z, v);
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544      /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+local int inflate_trees_fixed( /* bl, bd, tl, td, z) */
+uIntf *bl,                      /* literal desired/actual bit depth */
+uIntf *bd,                      /* distance desired/actual bit depth */
+const inflate_huft * FAR *tl,   /* literal/length tree result */
+const inflate_huft * FAR *td,   /* distance tree result */
+z_streamp z                     /* for memory allocation */
+)
+{
+#ifdef BUILDFIXED
+  /* build fixed tables if not already */
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    uInt f = 0;         /* number of hufts used in fixed_mem */
+    uIntf *c;           /* length list for huft_build */
+    uIntf *v;           /* work area for huft_build */
+
+    /* allocate memory */
+    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+      return Z_MEM_ERROR;
+    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    {
+      ZFREE(z, c);
+      return Z_MEM_ERROR;
+    }
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 9;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+               fixed_mem, &f, v);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+               fixed_mem, &f, v);
+
+    /* done */
+    ZFREE(z, v);
+    ZFREE(z, c);
+    fixed_built = 1;
+  }
+#else
+  FT_UNUSED(z);
+#endif
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
diff --git a/src/gzip/inftrees.h b/src/gzip/inftrees.h
new file mode 100644
index 0000000..07bf2aa
--- /dev/null
+++ b/src/gzip/inftrees.h
@@ -0,0 +1,63 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+local  int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+local  int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+local  int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    const inflate_huft * FAR *, /* literal/length tree result */
+    const inflate_huft * FAR *, /* distance tree result */
+    z_streamp));                /* for memory allocation */
+
+#endif /* _INFTREES_H */
diff --git a/src/gzip/infutil.c b/src/gzip/infutil.c
new file mode 100644
index 0000000..6087b40
--- /dev/null
+++ b/src/gzip/infutil.c
@@ -0,0 +1,86 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* And'ing with mask[n] masks the lower n bits */
+local const uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+  uInt n;
+  Bytef *p;
+  Bytef *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
diff --git a/src/gzip/infutil.h b/src/gzip/infutil.h
new file mode 100644
index 0000000..7174b6d
--- /dev/null
+++ b/src/gzip/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single malloc for tree space */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+#ifndef NO_INFLATE_MASK
+local uInt inflate_mask[17];
+#endif
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+#endif
diff --git a/src/gzip/zconf.h b/src/gzip/zconf.h
new file mode 100644
index 0000000..3abf0ba
--- /dev/null
+++ b/src/gzip/zconf.h
@@ -0,0 +1,284 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_         z_deflateInit_
+#  define deflate              z_deflate
+#  define deflateEnd           z_deflateEnd
+#  define inflateInit_         z_inflateInit_
+#  define inflate              z_inflate
+#  define inflateEnd           z_inflateEnd
+#  define deflateInit2_        z_deflateInit2_
+#  define deflateSetDictionary z_deflateSetDictionary
+#  define deflateCopy          z_deflateCopy
+#  define deflateReset         z_deflateReset
+#  define deflateParams        z_deflateParams
+#  define inflateInit2_        z_inflateInit2_
+#  define inflateSetDictionary z_inflateSetDictionary
+#  define inflateSync          z_inflateSync
+#  define inflateSyncPoint     z_inflateSyncPoint
+#  define inflateReset         z_inflateReset
+#  define compress             z_compress
+#  define compress2            z_compress2
+#  define uncompress           z_uncompress
+#  define adler32              z_adler32
+#  define crc32                z_crc32
+#  define get_crc_table        z_get_crc_table
+
+#  define Byte   z_Byte
+#  define uInt   z_uInt
+#  define uLong  z_uLong
+#  define Bytef  z_Bytef
+#  define charf  z_charf
+#  define intf   z_intf
+#  define uIntf  z_uIntf
+#  define uLongf z_uLongf
+#  define voidpf z_voidpf
+#  define voidp  z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+/* WinCE doesn't have errno.h */
+#ifdef _WIN32_WCE
+#  define NO_ERRNO_H
+#endif
+
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
+#  define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C and LCC incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#  define NEED_DUMMY_RETURN
+#endif
+
+#if defined(__LCC__)
+#  define  NEED_DUMMY_RETURN
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+   /* MSC small or medium model */
+#  define SMALL_MEDIUM
+#  ifdef _MSC_VER
+#    define FAR _far
+#  else
+#    define FAR far
+#  endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+#  ifndef __32BIT__
+#    define SMALL_MEDIUM
+#    define FAR _far
+#  endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+#  if defined(_WINDOWS) || defined(WINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define ZEXPORT(x)  x WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA(x)  x WINAPIV
+#    else
+#      define ZEXPORTVA(x)  x FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+#      define ZEXPORT(x) x __declspec(dllexport) WINAPI
+#      define ZEXPORTRVA(x)  x __declspec(dllexport) WINAPIV
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define ZEXPORT(x) x _export
+#        define ZEXPORTVA(x) x _export
+#      endif
+#    endif
+#  endif
+#endif
+
+
+#ifndef ZEXPORT
+#  define ZEXPORT(x)   static x
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA(x)   static x
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN(x) static x
+#endif
+#ifndef ZEXTERNDEF
+#  define ZEXTERNDEF(x)  static x
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  define z_off_t  off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define  z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(inflate_blocks,"INBL")
+#   pragma map(inflate_blocks_new,"INBLNE")
+#   pragma map(inflate_blocks_free,"INBLFR")
+#   pragma map(inflate_blocks_reset,"INBLRE")
+#   pragma map(inflate_codes_free,"INCOFR")
+#   pragma map(inflate_codes,"INCO")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_flush,"INFLU")
+#   pragma map(inflate_mask,"INMA")
+#   pragma map(inflate_set_dictionary,"INSEDI2")
+#   pragma map(inflate_copyright,"INCOPY")
+#   pragma map(inflate_trees_bits,"INTRBI")
+#   pragma map(inflate_trees_dynamic,"INTRDY")
+#   pragma map(inflate_trees_fixed,"INTRFI")
+#   pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/src/gzip/zlib.h b/src/gzip/zlib.h
new file mode 100644
index 0000000..50d0d3f
--- /dev/null
+++ b/src/gzip/zlib.h
@@ -0,0 +1,830 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.4, March 11th, 2002
+
+  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.4"
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+
+                        /* basic functions */
+
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN(int)  deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN(int)  inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN(int) inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+  it sets strm->adler to the adler32 checksum of all output produced
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+ZEXTERN(int)  inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN(int)  deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN(int)  inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+/*
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN(int)  inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+/*
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN(uLong)  adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN(int)  inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/src/gzip/zutil.c b/src/gzip/zutil.c
new file mode 100644
index 0000000..7ad0c1f
--- /dev/null
+++ b/src/gzip/zutil.c
@@ -0,0 +1,181 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC )
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* MSDOS && __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC )
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  ft_scalloc OF((uInt items, uInt size));
+extern void   ft_sfree   OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return (voidpf)ft_scalloc(items, size);
+}
+
+void  zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    ft_sfree(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/src/gzip/zutil.h b/src/gzip/zutil.h
new file mode 100644
index 0000000..c9688cd
--- /dev/null
+++ b/src/gzip/zutil.h
@@ -0,0 +1,215 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#ifdef MSDOS
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#     include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#  endif
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+#  define OS_CODE  0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0F
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#  define fdopen(fd,type)  _fdopen(fd,type)
+#endif
+
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) ft_fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#ifdef HAVE_STRERROR
+   extern char *strerror OF((int));
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy ft_memcpy
+#    define zmemcmp ft_memcmp
+#    define zmemzero(dest, len) ft_memset(dest, 0, len)
+#  endif
+#else
+   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
+   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
+   extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Bytef *buf,
+                                uInt len));
+local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+local void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 9285efc..f75bae4 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-2004, 2006, 2010, 2012 by                               */
+/*  Copyright 2001-2004, 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        */
@@ -757,7 +757,7 @@
                          FT_Fixed     x_delta,
                          FT_Fixed     y_delta )
   {
-    PSH_Dimension  dim = &globals->dimension[0];
+    PSH_Dimension  dim;
 
 
     dim = &globals->dimension[0];
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index 4865994..8aa1113 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -24,8 +24,8 @@
   /*                                                                       */
   /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
   /*                                                                       */
-  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */
-  /*   to your current directory                                           */
+  /* - copy `include/ftimage.h' and `src/raster/ftmisc.h' to your current  */
+  /*   directory                                                           */
   /*                                                                       */
   /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
   /*                                                                       */
@@ -453,8 +453,10 @@
 #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
 #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 )
+#define IS_BOTTOM_OVERSHOOT( x ) \
+          (Bool)( CEILING( x ) - x >= ras.precision_half )
+#define IS_TOP_OVERSHOOT( x )    \
+          (Bool)( x - FLOOR( x ) >= ras.precision_half )
 
   /* The most used variables are positioned at the top of the structure. */
   /* Thus, their offset can be coded with less opcodes, resulting in a   */
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 408f879..878de1f 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -122,7 +122,7 @@
   error_callback( png_structp      png,
                   png_const_charp  error_msg )
   {
-    FT_Error*  error = png_get_error_ptr( png );
+    FT_Error*  error = (FT_Error*)png_get_error_ptr( png );
 
     FT_UNUSED( error_msg );
 
@@ -159,7 +159,7 @@
 
     if ( FT_FRAME_ENTER( length ) )
     {
-      FT_Error*  e = png_get_error_ptr( png );
+      FT_Error*  e = (FT_Error*)png_get_error_ptr( png );
 
 
       *e = FT_THROW( Invalid_Stream_Read );
@@ -174,16 +174,18 @@
   }
 
 
-  static FT_Error
-  Load_SBit_Png( FT_Bitmap*       map,
+  FT_LOCAL_DEF( FT_Error )
+  Load_SBit_Png( FT_GlyphSlot     slot,
                  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_UInt          png_len,
+                 FT_Bool          populate_map_and_metrics )
   {
+    FT_Bitmap    *map   = &slot->bitmap;
     FT_Error      error = FT_Err_Ok;
     FT_StreamRec  stream;
 
@@ -193,12 +195,21 @@
 
     int         bitdepth, color_type, interlace;
     FT_Int      i;
-    png_byte*  *rows;
+    png_byte*  *rows = NULL; /* pacify compiler */
 
 
-    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 )
+    if ( x_offset < 0 ||
+         y_offset < 0 )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !populate_map_and_metrics                   &&
+         ( x_offset + metrics->width  > map->width ||
+           y_offset + metrics->height > map->rows  ||
+           pix_bits != 32                          ||
+           map->pixel_mode != FT_PIXEL_MODE_BGRA   ) )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -238,11 +249,33 @@
                   &bitdepth, &color_type, &interlace,
                   NULL, NULL );
 
-    if ( error != FT_Err_Ok                   ||
-         (FT_Int)imgWidth  != metrics->width  ||
-         (FT_Int)imgHeight != metrics->height )
+    if ( error                                        ||
+         ( !populate_map_and_metrics                &&
+           ( (FT_Int)imgWidth  != metrics->width  ||
+             (FT_Int)imgHeight != metrics->height ) ) )
       goto DestroyExit;
 
+    if ( populate_map_and_metrics )
+    {
+      FT_Long  size;
+
+
+      metrics->width  = (FT_Int)imgWidth;
+      metrics->height = (FT_Int)imgHeight;
+
+      map->width      = metrics->width;
+      map->rows       = metrics->height;
+      map->pixel_mode = FT_PIXEL_MODE_BGRA;
+      map->pitch      = map->width * 4;
+      map->num_grays  = 256;
+
+      size = map->rows * map->pitch;
+
+      error = ft_glyphslot_alloc_bitmap( slot, size );
+      if ( error )
+        goto DestroyExit;
+    }
+
     /* convert palette/gray image to rgb */
     if ( color_type == PNG_COLOR_TYPE_PALETTE )
       png_set_palette_to_rgb( png );
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
index 8a2e69c..dc9ecaf 100644
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -29,14 +29,15 @@
 #ifdef FT_CONFIG_OPTION_USE_PNG
 
   FT_LOCAL( FT_Error )
-  Load_SBit_Png( FT_Bitmap*       map,
+  Load_SBit_Png( FT_GlyphSlot     slot,
                  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_UInt          png_len,
+                 FT_Bool          populate_map_and_metrics );
 
 #endif
 
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index a368b8c..e0132c9 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -499,8 +499,8 @@
     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_sbit ),
+    PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
 
     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index f975e71..a31c77c 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -27,6 +27,7 @@
 #include FT_TRUETYPE_TAGS_H
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include FT_SFNT_NAMES_H
+#include FT_GZIP_H
 #include "sferrors.h"
 
 #ifdef TT_CONFIG_OPTION_BDF
@@ -347,6 +348,380 @@
   }
 
 
+#define WRITE_BYTE( p, v )     \
+          do                   \
+          {                    \
+            *(p)++ = (v) >> 0; \
+                               \
+          } while ( 0 )
+
+#define WRITE_USHORT( p, v )   \
+          do                   \
+          {                    \
+            *(p)++ = (v) >> 8; \
+            *(p)++ = (v) >> 0; \
+                               \
+          } while ( 0 )
+
+#define WRITE_ULONG( p, v )     \
+          do                    \
+          {                     \
+            *(p)++ = (v) >> 24; \
+            *(p)++ = (v) >> 16; \
+            *(p)++ = (v) >>  8; \
+            *(p)++ = (v) >>  0; \
+                                \
+          } while ( 0 )
+
+
+  static void
+  sfnt_stream_close( FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+
+
+    FT_FREE( stream->base );
+
+    stream->size  = 0;
+    stream->base  = 0;
+    stream->close = 0;
+  }
+
+
+  FT_CALLBACK_DEF( int )
+  compare_offsets( const void*  a,
+                   const void*  b )
+  {
+    WOFF_Table  table1 = *(WOFF_Table*)a;
+    WOFF_Table  table2 = *(WOFF_Table*)b;
+
+    FT_ULong  offset1 = table1->Offset;
+    FT_ULong  offset2 = table2->Offset;
+
+
+    if ( offset1 > offset2 )
+      return 1;
+    else if ( offset1 < offset2 )
+      return -1;
+    else
+      return 0;
+  }
+
+
+  /* Replace `face->root.stream' with a stream containing the extracted */
+  /* SFNT of a WOFF font.                                               */
+
+  static FT_Error
+  woff_open_font( FT_Stream  stream,
+                  TT_Face    face )
+  {
+    FT_Memory       memory = stream->memory;
+    FT_Error        error  = FT_Err_Ok;
+
+    WOFF_HeaderRec  woff;
+    WOFF_Table      tables  = NULL;
+    WOFF_Table*     indices = NULL;
+
+    FT_ULong        woff_offset;
+
+    FT_Byte*        sfnt        = NULL;
+    FT_Stream       sfnt_stream = NULL;
+
+    FT_Byte*        sfnt_header;
+    FT_ULong        sfnt_offset;
+
+    FT_Int          nn;
+    FT_ULong        old_tag = 0;
+
+    static const FT_Frame_Field  woff_header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  WOFF_HeaderRec
+
+      FT_FRAME_START( 44 ),
+        FT_FRAME_ULONG ( signature ),
+        FT_FRAME_ULONG ( flavor ),
+        FT_FRAME_ULONG ( length ),
+        FT_FRAME_USHORT( num_tables ),
+        FT_FRAME_USHORT( reserved ),
+        FT_FRAME_ULONG ( totalSfntSize ),
+        FT_FRAME_USHORT( majorVersion ),
+        FT_FRAME_USHORT( minorVersion ),
+        FT_FRAME_ULONG ( metaOffset ),
+        FT_FRAME_ULONG ( metaLength ),
+        FT_FRAME_ULONG ( metaOrigLength ),
+        FT_FRAME_ULONG ( privOffset ),
+        FT_FRAME_ULONG ( privLength ),
+      FT_FRAME_END
+    };
+
+
+    FT_ASSERT( stream == face->root.stream );
+    FT_ASSERT( FT_STREAM_POS() == 0 );
+
+    if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) )
+      return error;
+
+    /* Make sure we don't recurse back here or hit TTC code. */
+    if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf )
+      return FT_THROW( Invalid_Table );
+
+    /* Miscellaneous checks. */
+    if ( woff.length != stream->size                              ||
+         woff.num_tables == 0                                     ||
+         44 + woff.num_tables * 20UL >= woff.length               ||
+         12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
+         ( woff.totalSfntSize & 3 ) != 0                          ||
+         ( woff.metaOffset == 0 && ( woff.metaLength != 0     ||
+                                     woff.metaOrigLength != 0 ) ) ||
+         ( woff.metaLength != 0 && woff.metaOrigLength == 0 )     ||
+         ( woff.privOffset == 0 && woff.privLength != 0 )         )
+      return FT_THROW( Invalid_Table );
+
+    if ( FT_ALLOC( sfnt, woff.totalSfntSize ) ||
+         FT_NEW( sfnt_stream )                )
+      goto Exit;
+
+    sfnt_header = sfnt;
+
+    /* Write sfnt header. */
+    {
+      FT_UInt  searchRange, entrySelector, rangeShift, x;
+
+
+      x             = woff.num_tables;
+      entrySelector = 0;
+      while ( x )
+      {
+        x            >>= 1;
+        entrySelector += 1;
+      }
+      entrySelector--;
+
+      searchRange = ( 1 << entrySelector ) * 16;
+      rangeShift  = woff.num_tables * 16 - searchRange;
+
+      WRITE_ULONG ( sfnt_header, woff.flavor );
+      WRITE_USHORT( sfnt_header, woff.num_tables );
+      WRITE_USHORT( sfnt_header, searchRange );
+      WRITE_USHORT( sfnt_header, entrySelector );
+      WRITE_USHORT( sfnt_header, rangeShift );
+    }
+
+    /* While the entries in the sfnt header must be sorted by the */
+    /* tag value, the tables themselves are not.  We thus have to */
+    /* sort them by offset and check that they don't overlap.     */
+
+    if ( FT_NEW_ARRAY( tables, woff.num_tables )  ||
+         FT_NEW_ARRAY( indices, woff.num_tables ) )
+      goto Exit;
+
+    FT_TRACE2(( "\n"
+                "  tag    offset    compLen  origLen  checksum\n"
+                "  -------------------------------------------\n" ));
+
+    if ( FT_FRAME_ENTER( 20L * woff.num_tables ) )
+      goto Exit;
+
+    for ( nn = 0; nn < woff.num_tables; nn++ )
+    {
+      WOFF_Table  table = tables + nn;
+
+      table->Tag        = FT_GET_TAG4();
+      table->Offset     = FT_GET_ULONG();
+      table->CompLength = FT_GET_ULONG();
+      table->OrigLength = FT_GET_ULONG();
+      table->CheckSum   = FT_GET_ULONG();
+
+      FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx  %08lx\n",
+                  (FT_Char)( table->Tag >> 24 ),
+                  (FT_Char)( table->Tag >> 16 ),
+                  (FT_Char)( table->Tag >> 8  ),
+                  (FT_Char)( table->Tag       ),
+                  table->Offset,
+                  table->CompLength,
+                  table->OrigLength,
+                  table->CheckSum ));
+
+      if ( table->Tag <= old_tag )
+      {
+        FT_FRAME_EXIT();
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      old_tag     = table->Tag;
+      indices[nn] = table;
+    }
+
+    FT_FRAME_EXIT();
+
+    /* Sort by offset. */
+
+    ft_qsort( indices,
+              woff.num_tables,
+              sizeof ( WOFF_Table ),
+              compare_offsets );
+
+    /* Check offsets and lengths. */
+
+    woff_offset = 44 + woff.num_tables * 20L;
+    sfnt_offset = 12 + woff.num_tables * 16L;
+
+    for ( nn = 0; nn < woff.num_tables; nn++ )
+    {
+      WOFF_Table  table = indices[nn];
+
+
+      if ( table->Offset != woff_offset                         ||
+           table->Offset + table->CompLength > woff.length      ||
+           sfnt_offset + table->OrigLength > woff.totalSfntSize ||
+           table->CompLength > table->OrigLength                )
+      {
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      table->OrigOffset = sfnt_offset;
+
+      /* The offsets must be multiples of 4. */
+      woff_offset += ( table->CompLength + 3 ) & ~3;
+      sfnt_offset += ( table->OrigLength + 3 ) & ~3;
+    }
+
+    /*
+     * Final checks!
+     *
+     * We don't decode and check the metadata block.
+     * We don't check table checksums either.
+     * But other than those, I think we implement all
+     * `MUST' checks from the spec.
+     */
+
+    if ( woff.metaOffset )
+    {
+      if ( woff.metaOffset != woff_offset                  ||
+           woff.metaOffset + woff.metaLength > woff.length )
+      {
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      /* We have padding only ... */
+      woff_offset += woff.metaLength;
+    }
+
+    if ( woff.privOffset )
+    {
+      /* ... if it isn't the last block. */
+      woff_offset = ( woff_offset + 3 ) & ~3;
+
+      if ( woff.privOffset != woff_offset                  ||
+           woff.privOffset + woff.privLength > woff.length )
+      {
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      /* No padding for the last block. */
+      woff_offset += woff.privLength;
+    }
+
+    if ( sfnt_offset != woff.totalSfntSize ||
+         woff_offset != woff.length        )
+    {
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    /* Write the tables. */
+
+    for ( nn = 0; nn < woff.num_tables; nn++ )
+    {
+      WOFF_Table  table = tables + nn;
+
+
+      /* Write SFNT table entry. */
+      WRITE_ULONG( sfnt_header, table->Tag );
+      WRITE_ULONG( sfnt_header, table->CheckSum );
+      WRITE_ULONG( sfnt_header, table->OrigOffset );
+      WRITE_ULONG( sfnt_header, table->OrigLength );
+
+      /* Write table data. */
+      if ( FT_STREAM_SEEK( table->Offset )     ||
+           FT_FRAME_ENTER( table->CompLength ) )
+        goto Exit;
+
+      if ( table->CompLength == table->OrigLength )
+      {
+        /* Uncompressed data; just copy. */
+        ft_memcpy( sfnt + table->OrigOffset,
+                   stream->cursor,
+                   table->OrigLength );
+      }
+      else
+      {
+        /* Uncompress with zlib. */
+        FT_ULong  output_len = table->OrigLength;
+
+
+        error = FT_Gzip_Uncompress( memory,
+                                    sfnt + table->OrigOffset, &output_len,
+                                    stream->cursor, table->CompLength );
+        if ( error )
+          goto Exit;
+        if ( output_len != table->OrigLength )
+        {
+          error = FT_THROW( Invalid_Table );
+          goto Exit;
+        }
+      }
+
+      FT_FRAME_EXIT();
+
+      /* We don't check whether the padding bytes in the WOFF file are     */
+      /* actually '\0'.  For the output, however, we do set them properly. */
+      sfnt_offset = table->OrigOffset + table->OrigLength;
+      while ( sfnt_offset & 3 )
+      {
+        sfnt[sfnt_offset] = '\0';
+        sfnt_offset++;
+      }
+    }
+
+    /* Ok!  Finally ready.  Swap out stream and return. */
+    FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize );
+    sfnt_stream->memory = stream->memory;
+    sfnt_stream->close  = sfnt_stream_close;
+
+    FT_Stream_Free(
+      face->root.stream,
+      ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
+
+    face->root.stream = sfnt_stream;
+
+    face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+
+  Exit:
+    FT_FREE( tables );
+    FT_FREE( indices );
+
+    if ( error )
+    {
+      FT_FREE( sfnt );
+      FT_Stream_Close( sfnt_stream );
+      FT_FREE( sfnt_stream );
+    }
+
+    return error;
+  }
+
+
+#undef WRITE_BYTE
+#undef WRITE_USHORT
+#undef WRITE_ULONG
+
+
   /* Fill in face->ttc_header.  If the font is not a TTC, it is */
   /* synthesized into a TTC with one offset table.              */
   static FT_Error
@@ -373,11 +748,28 @@
     face->ttc_header.version = 0;
     face->ttc_header.count   = 0;
 
+  retry:
     offset = FT_STREAM_POS();
 
     if ( FT_READ_ULONG( tag ) )
       return error;
 
+    if ( tag == TTAG_wOFF )
+    {
+      FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
+
+      if ( FT_STREAM_SEEK( offset ) )
+        return error;
+
+      error = woff_open_font( stream, face );
+      if ( error )
+        return error;
+
+      /* Swap out stream and retry! */
+      stream = face->root.stream;
+      goto retry;
+    }
+
     if ( tag != 0x00010000UL &&
          tag != TTAG_ttcf    &&
          tag != TTAG_OTTO    &&
@@ -480,6 +872,9 @@
     if ( error )
       return error;
 
+    /* Stream may have changed in sfnt_open_font. */
+    stream = face->root.stream;
+
     FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
 
     if ( face_index < 0 )
@@ -504,7 +899,8 @@
 
 
 #define LOAD_( x )                                          \
-  do {                                                      \
+  do                                                        \
+  {                                                         \
     FT_TRACE2(( "`" #x "' " ));                             \
     FT_TRACE3(( "-->\n" ));                                 \
                                                             \
@@ -519,7 +915,8 @@
   } while ( 0 )
 
 #define LOADM_( x, vertical )                               \
-  do {                                                      \
+  do                                                        \
+  {                                                         \
     FT_TRACE2(( "`%s" #x "' ",                              \
                 vertical ? "vertical " : "" ));             \
     FT_TRACE3(( "-->\n" ));                                 \
@@ -535,7 +932,8 @@
   } while ( 0 )
 
 #define GET_NAME( id, field )                                   \
-  do {                                                          \
+  do                                                            \
+  {                                                             \
     error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
     if ( error )                                                \
       goto Exit;                                                \
@@ -555,6 +953,7 @@
 #endif
     FT_Bool       has_outline;
     FT_Bool       is_apple_sbit;
+    FT_Bool       is_apple_sbix;
     FT_Bool       ignore_preferred_family    = FALSE;
     FT_Bool       ignore_preferred_subfamily = FALSE;
 
@@ -608,6 +1007,14 @@
 #endif
 
     is_apple_sbit = 0;
+    is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
+
+    /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
+     * outline rendered on top.  We don't support that yet, so just ignore
+     * the 'glyf' outline and advertise it as a bitmap-only font. */
+    if ( is_apple_sbix )
+      has_outline = FALSE;
+
 
     /* if this font doesn't contain outlines, we try to load */
     /* a `bhed' table                                        */
@@ -619,7 +1026,7 @@
 
     /* load the font header (`head' table) if this isn't an Apple */
     /* sbit font file                                             */
-    if ( !is_apple_sbit )
+    if ( !is_apple_sbit || is_apple_sbix )
     {
       LOAD_( head );
       if ( error )
@@ -803,6 +1210,10 @@
       /*                                                                   */
       /* Compute face flags.                                               */
       /*                                                                   */
+      if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
+           face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
+        flags |= FT_FACE_FLAG_COLOR;      /* color glyphs */
+
       if ( has_outline == TRUE )
         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
 
@@ -931,7 +1342,7 @@
 
           if ( em_size == 0 || face->os2.version == 0xFFFFU )
           {
-            avgwidth = 0;
+            avgwidth = 1;
             em_size = 1;
           }
 
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 1507202..9b7856b 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -320,9 +320,8 @@
     /* parse sub-headers */
     for ( n = 0; n <= max_subs; n++ )
     {
-      FT_UInt   first_code, code_count, offset;
-      FT_Int    delta;
-      FT_Byte*  ids;
+      FT_UInt  first_code, code_count, offset;
+      FT_Int   delta;
 
 
       first_code = TT_NEXT_USHORT( p );
@@ -344,6 +343,9 @@
       /* check offset */
       if ( offset != 0 )
       {
+        FT_Byte*  ids;
+
+
         ids = p - 2 + offset;
         if ( ids < glyph_ids || ids + code_count*2 > table + length )
           FT_INVALID_OFFSET;
@@ -3208,7 +3210,6 @@
   {
     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
                                              variantSelector );
-    FT_UInt32  *ret;
     FT_Int      i;
     FT_ULong    defOff;
     FT_ULong    nondefOff;
@@ -3242,6 +3243,8 @@
       FT_Byte*   dp;
       FT_UInt    di, ni, k;
 
+      FT_UInt32  *ret;
+
 
       p  = cmap->data + nondefOff;
       dp = cmap->data + defOff;
diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c
index 60ee546..32c4008 100644
--- a/src/sfnt/ttkern.c
+++ b/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
 /*    Load the basic TrueType kerning table.  This doesn't handle          */
 /*    kerning data within the GPOS table at the moment.                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/*  Copyright 1996-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,       */
@@ -183,7 +183,7 @@
                        FT_UInt  right_glyph )
   {
     FT_Int    result = 0;
-    FT_UInt   count, mask = 1;
+    FT_UInt   count, mask;
     FT_Byte*  p       = face->kern_table;
     FT_Byte*  p_limit = p + face->kern_table_size;
 
@@ -196,7 +196,7 @@
           count--, mask <<= 1 )
     {
       FT_Byte* base     = p;
-      FT_Byte* next     = base;
+      FT_Byte* next;
       FT_UInt  version  = FT_NEXT_USHORT( p );
       FT_UInt  length   = FT_NEXT_USHORT( p );
       FT_UInt  coverage = FT_NEXT_USHORT( p );
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index fbe70f7..0a3cd29 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -236,7 +236,8 @@
          */
         if ( table.Length < 0x36 )
         {
-          FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
+          FT_TRACE2(( "check_table_dir:"
+                      " `head' or `bhed' table too small\n" ));
           error = FT_THROW( Table_Missing );
           goto Exit;
         }
@@ -246,12 +247,8 @@
           goto Exit;
 
         if ( magic != 0x5F0F3CF5UL )
-        {
           FT_TRACE2(( "check_table_dir:"
-                      " no magic number found in `head' table\n"));
-          error = FT_THROW( Table_Missing );
-          goto Exit;
-        }
+                      " invalid magic number in `head' or `bhed' table\n"));
 
         if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
           goto Exit;
@@ -394,8 +391,8 @@
     {
       entry->Tag      = FT_GET_TAG4();
       entry->CheckSum = FT_GET_ULONG();
-      entry->Offset   = FT_GET_LONG();
-      entry->Length   = FT_GET_LONG();
+      entry->Offset   = FT_GET_ULONG();
+      entry->Length   = FT_GET_ULONG();
 
       /* ignore invalid tables */
       if ( entry->Offset + entry->Length > stream->size )
@@ -1006,7 +1003,8 @@
       FT_FRAME_END
     };
 
-    static const FT_Frame_Field  os2_fields_extra[] =
+    /* `OS/2' version 1 and newer */
+    static const FT_Frame_Field  os2_fields_extra1[] =
     {
       FT_FRAME_START( 8 ),
         FT_FRAME_ULONG( ulCodePageRange1 ),
@@ -1014,6 +1012,7 @@
       FT_FRAME_END
     };
 
+    /* `OS/2' version 2 and newer */
     static const FT_Frame_Field  os2_fields_extra2[] =
     {
       FT_FRAME_START( 10 ),
@@ -1025,6 +1024,15 @@
       FT_FRAME_END
     };
 
+    /* `OS/2' version 5 and newer */
+    static const FT_Frame_Field  os2_fields_extra5[] =
+    {
+      FT_FRAME_START( 4 ),
+        FT_FRAME_USHORT( usLowerOpticalPointSize ),
+        FT_FRAME_USHORT( usUpperOpticalPointSize ),
+      FT_FRAME_END
+    };
+
 
     /* We now support old Mac fonts where the OS/2 table doesn't  */
     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
@@ -1038,18 +1046,20 @@
     if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
       goto Exit;
 
-    os2->ulCodePageRange1 = 0;
-    os2->ulCodePageRange2 = 0;
-    os2->sxHeight         = 0;
-    os2->sCapHeight       = 0;
-    os2->usDefaultChar    = 0;
-    os2->usBreakChar      = 0;
-    os2->usMaxContext     = 0;
+    os2->ulCodePageRange1        = 0;
+    os2->ulCodePageRange2        = 0;
+    os2->sxHeight                = 0;
+    os2->sCapHeight              = 0;
+    os2->usDefaultChar           = 0;
+    os2->usBreakChar             = 0;
+    os2->usMaxContext            = 0;
+    os2->usLowerOpticalPointSize = 0;
+    os2->usUpperOpticalPointSize = 0xFFFF;
 
     if ( os2->version >= 0x0001 )
     {
       /* only version 1 tables */
-      if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
+      if ( FT_STREAM_READ_FIELDS( os2_fields_extra1, os2 ) )
         goto Exit;
 
       if ( os2->version >= 0x0002 )
@@ -1057,6 +1067,13 @@
         /* only version 2 tables */
         if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
           goto Exit;
+
+        if ( os2->version >= 0x0005 )
+        {
+          /* only version 5 tables */
+          if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) )
+            goto Exit;
+        }
       }
     }
 
@@ -1164,6 +1181,7 @@
         FT_FRAME_USHORT( Style ),
         FT_FRAME_USHORT( TypeFamily ),
         FT_FRAME_USHORT( CapHeight ),
+        FT_FRAME_USHORT( SymbolSet ),
         FT_FRAME_BYTES ( TypeFace, 16 ),
         FT_FRAME_BYTES ( CharacterComplement, 8 ),
         FT_FRAME_BYTES ( FileName, 6 ),
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 371a9ed..a8cc63a 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -183,20 +183,23 @@
   /*    tt_face_get_metrics                                                */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Returns the horizontal or vertical metrics in font units for a     */
-  /*    given glyph.  The metrics are the left side bearing (resp. top     */
-  /*    side bearing) and advance width (resp. advance height).            */
+  /*    Return the horizontal or vertical metrics in font units for a      */
+  /*    given glyph.  The values are the left side bearing (top side       */
+  /*    bearing for vertical metrics) and advance width (advance height    */
+  /*    for vertical metrics).                                             */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    header  :: A pointer to either the horizontal or vertical metrics  */
-  /*               structure.                                              */
+  /*    face     :: A pointer to the TrueType face structure.              */
   /*                                                                       */
-  /*    idx     :: The glyph index.                                        */
+  /*    vertical :: If set to TRUE, get vertical metrics.                  */
+  /*                                                                       */
+  /*    gindex   :: The glyph index.                                       */
   /*                                                                       */
   /* <Output>                                                              */
-  /*    bearing :: The bearing, either left side or top side.              */
+  /*    abearing :: The bearing, either left side or top side.             */
   /*                                                                       */
-  /*    advance :: The advance width resp. advance height.                 */
+  /*    aadvance :: The advance width or advance height, depending on      */
+  /*                the `vertical' flag.                                   */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
   tt_face_get_metrics( TT_Face     face,
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index cd3e5a4..7469ff1 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -28,6 +28,7 @@
 
 #include "sferrors.h"
 
+#include "ttmtx.h"
 #include "pngshim.h"
 
 
@@ -42,25 +43,36 @@
 
 
   FT_LOCAL_DEF( FT_Error )
-  tt_face_load_eblc( TT_Face    face,
+  tt_face_load_sbit( TT_Face    face,
                      FT_Stream  stream )
   {
-    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;
+    FT_Error  error;
+    FT_ULong  table_size;
 
 
+    face->sbit_table       = NULL;
+    face->sbit_table_size  = 0;
+    face->sbit_table_type  = TT_SBIT_TABLE_TYPE_NONE;
     face->sbit_num_strikes = 0;
 
-    /* this table is optional */
     error = face->goto_table( face, TTAG_CBLC, stream, &table_size );
-    if ( error )
+    if ( !error )
+      face->sbit_table_type = TT_SBIT_TABLE_TYPE_CBLC;
+    else
+    {
       error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
+      if ( error )
+        error = face->goto_table( face, TTAG_bloc, stream, &table_size );
+      if ( !error )
+        face->sbit_table_type = TT_SBIT_TABLE_TYPE_EBLC;
+    }
+
     if ( error )
-      error = face->goto_table( face, TTAG_bloc, stream, &table_size );
+    {
+      error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+      if ( !error )
+        face->sbit_table_type = TT_SBIT_TABLE_TYPE_SBIX;
+    }
     if ( error )
       goto Exit;
 
@@ -71,53 +83,130 @@
       goto Exit;
     }
 
-    if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
-      goto Exit;
-
-    face->sbit_table_size = table_size;
-
-    p       = face->sbit_table;
-    p_limit = p + table_size;
-
-    version     = FT_NEXT_ULONG( p );
-    num_strikes = FT_NEXT_ULONG( p );
-
-    if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
+    switch ( (FT_UInt)face->sbit_table_type )
     {
-      FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
-      error = FT_THROW( Invalid_File_Format );
-      goto Fail;
+    case TT_SBIT_TABLE_TYPE_EBLC:
+    case TT_SBIT_TABLE_TYPE_CBLC:
+      {
+        FT_Byte*  p;
+        FT_Fixed  version;
+        FT_ULong  num_strikes;
+        FT_UInt   count;
+
+
+        if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
+          goto Exit;
+
+        face->sbit_table_size = table_size;
+
+        p = face->sbit_table;
+
+        version     = FT_NEXT_ULONG( p );
+        num_strikes = FT_NEXT_ULONG( p );
+
+        if ( ( version & 0xFFFF0000UL ) != 0x00020000UL )
+        {
+          error = FT_THROW( Unknown_File_Format );
+          goto Exit;
+        }
+
+        if ( num_strikes >= 0x10000UL )
+        {
+          error = FT_THROW( Invalid_File_Format );
+          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)( ( table_size - 8 ) / 48 );
+
+        face->sbit_num_strikes = count;
+      }
+      break;
+
+    case TT_SBIT_TABLE_TYPE_SBIX:
+      {
+        FT_UShort  version;
+        FT_UShort  flags;
+        FT_ULong   num_strikes;
+        FT_UInt    count;
+
+
+        if ( FT_FRAME_ENTER( 8 ) )
+          goto Exit;
+
+        version     = FT_GET_USHORT();
+        flags       = FT_GET_USHORT();
+        num_strikes = FT_GET_ULONG();
+
+        FT_FRAME_EXIT();
+
+        if ( version < 1 )
+        {
+          error = FT_THROW( Unknown_File_Format );
+          goto Exit;
+        }
+        if ( flags != 0x0001 || num_strikes >= 0x10000UL )
+        {
+          error = FT_THROW( Invalid_File_Format );
+          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 + 4UL * count > table_size )
+          count = (FT_UInt)( ( table_size - 8 ) / 4 );
+
+        if ( FT_STREAM_SEEK( FT_STREAM_POS() - 8 ) )
+          goto Exit;
+
+        face->sbit_table_size = 8 + count * 4;
+        if ( FT_FRAME_EXTRACT( face->sbit_table_size, face->sbit_table ) )
+          goto Exit;
+
+        face->sbit_num_strikes = count;
+      }
+      break;
+
+    default:
+      error = FT_THROW( Unknown_File_Format );
+      break;
     }
 
-    /*
-     *  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 );
+    if ( !error )
+      FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
 
-    face->sbit_num_strikes = count;
+    return FT_Err_Ok;
 
-    FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
   Exit:
-    return error;
+    if ( error )
+    {
+      if ( face->sbit_table )
+        FT_FRAME_RELEASE( face->sbit_table );
+      face->sbit_table_size = 0;
+      face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
+    }
 
-  Fail:
-    FT_FRAME_RELEASE( face->sbit_table );
-    face->sbit_table_size = 0;
-    goto Exit;
+    return error;
   }
 
 
   FT_LOCAL_DEF( void )
-  tt_face_free_eblc( TT_Face  face )
+  tt_face_free_sbit( TT_Face  face )
   {
     FT_Stream  stream = face->root.stream;
 
 
     FT_FRAME_RELEASE( face->sbit_table );
     face->sbit_table_size  = 0;
+    face->sbit_table_type  = TT_SBIT_TABLE_TYPE_NONE;
     face->sbit_num_strikes = 0;
   }
 
@@ -136,28 +225,85 @@
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics )
   {
-    FT_Byte*  strike;
-
-
     if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
       return FT_THROW( Invalid_Argument );
 
-    strike = face->sbit_table + 8 + strike_index * 48;
+    switch ( (FT_UInt)face->sbit_table_type )
+    {
+    case TT_SBIT_TABLE_TYPE_EBLC:
+    case TT_SBIT_TABLE_TYPE_CBLC:
+      {
+        FT_Byte*  strike;
 
-    metrics->x_ppem = (FT_UShort)strike[44];
-    metrics->y_ppem = (FT_UShort)strike[45];
 
-    metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
-    metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
-    metrics->height    = metrics->ascender - metrics->descender;
+        strike = face->sbit_table + 8 + strike_index * 48;
 
-    /* XXX: Is this correct? */
-    metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */
-                                      strike[18] + /* max_width      */
-                             (FT_Char)strike[23]   /* min_advance_SB */
-                                                 ) << 6;
+        metrics->x_ppem = (FT_UShort)strike[44];
+        metrics->y_ppem = (FT_UShort)strike[45];
 
-    return FT_Err_Ok;
+        metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
+        metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
+        metrics->height    = metrics->ascender - metrics->descender;
+
+        /* Is this correct? */
+        metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */
+                                          strike[18] + /* max_width      */
+                                 (FT_Char)strike[23]   /* min_advance_SB */
+                                                     ) << 6;
+        return FT_Err_Ok;
+      }
+
+    case TT_SBIT_TABLE_TYPE_SBIX:
+      {
+        FT_Stream       stream = face->root.stream;
+        FT_UInt         offset, ppem, resolution, upem;
+        TT_HoriHeader  *hori;
+        FT_ULong        table_size;
+
+        FT_Error  error;
+        FT_Byte*  p;
+
+
+        p      = face->sbit_table + 8 + 4 * strike_index;
+        offset = FT_NEXT_ULONG( p );
+
+        error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+        if ( error )
+          return error;
+
+        if ( offset + 4  > table_size )
+          return FT_THROW( Invalid_File_Format );
+
+        if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) ||
+             FT_FRAME_ENTER( 4 )                        )
+          return error;
+
+        ppem       = FT_GET_USHORT();
+        resolution = FT_GET_USHORT();
+
+        FT_UNUSED( resolution ); /* What to do with this? */
+
+        FT_FRAME_EXIT();
+
+        upem = face->header.Units_Per_EM;
+        hori = &face->horizontal;
+
+        metrics->x_ppem = ppem;
+        metrics->y_ppem = ppem;
+
+        metrics->ascender    = ppem * hori->Ascender * 64 / upem;
+        metrics->descender   = ppem * hori->Descender * 64 / upem;
+        metrics->height      = ppem * ( hori->Ascender -
+                                        hori->Descender +
+                                        hori->Line_Gap ) * 64 / upem;
+        metrics->max_advance = ppem * hori->advance_Width_Max * 64 / upem;
+
+        return error;
+      }
+
+    default:
+      return FT_THROW( Unknown_File_Format );
+    }
   }
 
 
@@ -253,8 +399,7 @@
 
 
   static FT_Error
-  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder,
-                                FT_UInt         load_flags )
+  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder )
   {
     FT_Error    error = FT_Err_Ok;
     FT_UInt     width, height;
@@ -301,18 +446,9 @@
       break;
 
     case 32:
-      if ( load_flags & FT_LOAD_COLOR )
-      {
-        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;
-      }
+      map->pixel_mode = FT_PIXEL_MODE_BGRA;
+      map->pitch      = map->width * 4;
+      map->num_grays  = 256;
       break;
 
     default:
@@ -382,13 +518,11 @@
   /* 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,
@@ -397,7 +531,6 @@
 
   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,
@@ -408,8 +541,6 @@
     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;
@@ -538,7 +669,6 @@
 
   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,
@@ -550,8 +680,6 @@
     FT_Bitmap*  bitmap;
     FT_UShort   rval;
 
-    FT_UNUSED( load_flags );
-
 
     /* check that we can write the glyph into the bitmap */
     bitmap     = decoder->bitmap;
@@ -664,7 +792,6 @@
 
   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,
@@ -702,7 +829,7 @@
 
 
       /* NB: a recursive call */
-      error = tt_sbit_decoder_load_image( decoder, load_flags, gindex,
+      error = tt_sbit_decoder_load_image( decoder, gindex,
                                           x_pos + dx, y_pos + dy );
       if ( error )
         break;
@@ -732,7 +859,6 @@
 
   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,
@@ -741,8 +867,6 @@
     FT_Error  error = FT_Err_Ok;
     FT_ULong  png_len;
 
-    FT_UNUSED( load_flags );
-
 
     if ( limit - p < 4 )
     {
@@ -759,14 +883,15 @@
       goto Exit;
     }
 
-    error = Load_SBit_Png( decoder->bitmap,
+    error = Load_SBit_Png( decoder->face->root.glyph,
                            x_pos,
                            y_pos,
                            decoder->bit_depth,
                            decoder->metrics,
                            decoder->stream->memory,
                            p,
-                           png_len );
+                           png_len,
+                           FALSE );
 
   Exit:
     if ( !error )
@@ -779,7 +904,6 @@
 
   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,
@@ -845,7 +969,32 @@
       case 2:
       case 5:
       case 7:
-        loader = tt_sbit_decoder_load_bit_aligned;
+        {
+          /* Don't trust `glyph_format'.  For example, Apple's main Korean */
+          /* system font, `AppleMyungJo.ttf' (version 7.0d2e6), uses glyph */
+          /* format 7, but the data is format 6.  We check whether we have */
+          /* an excessive number of bytes in the image: If it is equal to  */
+          /* the value for a byte-aligned glyph, use the other loading     */
+          /* routine.                                                      */
+          /*                                                               */
+          /* Note that for some (width,height) combinations, where the     */
+          /* width is not a multiple of 8, the sizes for bit- and          */
+          /* byte-aligned data are equal, for example (7,7) or (15,6).  We */
+          /* then prefer what `glyph_format' specifies.                    */
+
+          FT_UInt  width  = decoder->metrics->width;
+          FT_UInt  height = decoder->metrics->height;
+
+          FT_UInt  bit_size  = ( width * height + 7 ) >> 3;
+          FT_UInt  byte_size = height * ( ( width + 7 ) >> 3 );
+
+
+          if ( bit_size < byte_size                  &&
+               byte_size == (FT_UInt)( p_limit - p ) )
+            loader = tt_sbit_decoder_load_byte_aligned;
+          else
+            loader = tt_sbit_decoder_load_bit_aligned;
+        }
         break;
 
       case 8:
@@ -859,13 +1008,15 @@
         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 */
+#ifdef FT_CONFIG_OPTION_USE_PNG
         loader = tt_sbit_decoder_load_png;
-        break;
+#else
+        error = FT_THROW( Unimplemented_Feature );
 #endif /* FT_CONFIG_OPTION_USE_PNG */
+        break;
 
       default:
         error = FT_THROW( Invalid_Table );
@@ -874,64 +1025,12 @@
 
       if ( !decoder->bitmap_allocated )
       {
-        error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags );
+        error = tt_sbit_decoder_alloc_bitmap( decoder );
         if ( error )
           goto Fail;
       }
 
-      if ( decoder->bit_depth == 32                          &&
-           decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA )
-      {
-        /* Flatten color bitmaps if color was not requested. */
-
-        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 );
+      error = loader( decoder, p, p_limit, x_pos, y_pos );
     }
 
   Fail:
@@ -944,7 +1043,6 @@
 
   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 )
@@ -993,17 +1091,15 @@
     switch ( index_format )
     {
     case 1: /* 4-byte offsets relative to `image_offset' */
-      {
-        p += 4 * ( glyph_index - start );
-        if ( p + 8 > p_limit )
-          goto NoBitmap;
+      p += 4 * ( glyph_index - start );
+      if ( p + 8 > p_limit )
+        goto NoBitmap;
 
-        image_start = FT_NEXT_ULONG( p );
-        image_end   = FT_NEXT_ULONG( p );
+      image_start = FT_NEXT_ULONG( p );
+      image_end   = FT_NEXT_ULONG( p );
 
-        if ( image_start == image_end )  /* missing glyph */
-          goto NoBitmap;
-      }
+      if ( image_start == image_end )  /* missing glyph */
+        goto NoBitmap;
       break;
 
     case 2: /* big metrics, constant image size */
@@ -1025,17 +1121,15 @@
       break;
 
     case 3: /* 2-byte offsets relative to 'image_offset' */
-      {
-        p += 2 * ( glyph_index - start );
-        if ( p + 4 > p_limit )
-          goto NoBitmap;
+      p += 2 * ( glyph_index - start );
+      if ( p + 4 > p_limit )
+        goto NoBitmap;
 
-        image_start = FT_NEXT_USHORT( p );
-        image_end   = FT_NEXT_USHORT( p );
+      image_start = FT_NEXT_USHORT( p );
+      image_end   = FT_NEXT_USHORT( p );
 
-        if ( image_start == image_end )  /* missing glyph */
-          goto NoBitmap;
-      }
+      if ( image_start == image_end )  /* missing glyph */
+        goto NoBitmap;
       break;
 
     case 4: /* sparse glyph array with (glyph,offset) pairs */
@@ -1124,7 +1218,6 @@
                 image_format, glyph_index ));
 
     return tt_sbit_decoder_load_bitmap( decoder,
-                                        load_flags,
                                         image_format,
                                         image_start,
                                         image_end,
@@ -1142,6 +1235,129 @@
   }
 
 
+  static FT_Error
+  tt_face_load_sbix_image( TT_Face              face,
+                           FT_ULong             strike_index,
+                           FT_UInt              glyph_index,
+                           FT_Stream            stream,
+                           FT_Bitmap           *map,
+                           TT_SBit_MetricsRec  *metrics )
+  {
+    FT_UInt     sbix_pos, strike_offset, glyph_start, glyph_end;
+    FT_ULong    table_size, data_size;
+    FT_Int      originOffsetX, originOffsetY;
+    FT_Tag      graphicType;
+    FT_Int      recurse_depth = 0;
+
+    FT_Error  error;
+    FT_Byte*  p;
+
+    FT_UNUSED( map );
+
+
+    metrics->width  = 0;
+    metrics->height = 0;
+
+    p = face->sbit_table + 8 + 4 * strike_index;
+    strike_offset = FT_NEXT_ULONG( p );
+
+    error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+    if ( error )
+      return error;
+    sbix_pos = FT_STREAM_POS();
+
+  retry:
+    if ( glyph_index > (FT_UInt)face->root.num_glyphs )
+      return FT_THROW( Invalid_Argument );
+
+    if ( strike_offset >= table_size                          ||
+         table_size - strike_offset < 4 + glyph_index * 4 + 8 )
+      return FT_THROW( Invalid_File_Format );
+
+    if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) ||
+         FT_FRAME_ENTER( 8 )                                              )
+      return error;
+
+    glyph_start = FT_GET_ULONG();
+    glyph_end   = FT_GET_ULONG();
+
+    FT_FRAME_EXIT();
+
+    if ( glyph_start == glyph_end )
+      return FT_THROW( Invalid_Argument );
+    if ( glyph_start > glyph_end                ||
+         glyph_end - glyph_start < 8            ||
+         table_size - strike_offset < glyph_end )
+      return FT_THROW( Invalid_File_Format );
+
+    if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) ||
+         FT_FRAME_ENTER( glyph_end - glyph_start )                )
+      return error;
+
+    originOffsetX = FT_GET_SHORT();
+    originOffsetY = FT_GET_SHORT();
+
+    graphicType = FT_GET_TAG4();
+    data_size   = glyph_end - glyph_start - 8;
+
+    switch ( graphicType )
+    {
+    case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ):
+      if ( recurse_depth < 4 )
+      {
+        glyph_index = FT_GET_USHORT();
+        FT_FRAME_EXIT();
+        recurse_depth++;
+        goto retry;
+      }
+      error = FT_THROW( Invalid_File_Format );
+      break;
+
+    case FT_MAKE_TAG( 'p', 'n', 'g', ' ' ):
+#ifdef FT_CONFIG_OPTION_USE_PNG
+      error = Load_SBit_Png( face->root.glyph,
+                             0,
+                             0,
+                             32,
+                             metrics,
+                             stream->memory,
+                             stream->cursor,
+                             data_size,
+                             TRUE );
+#else
+      error = FT_THROW( Unimplemented_Feature );
+#endif
+      break;
+
+    case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ):
+    case FT_MAKE_TAG( 't', 'i', 'f', 'f' ):
+      error = FT_THROW( Unknown_File_Format );
+      break;
+
+    default:
+      error = FT_THROW( Unimplemented_Feature );
+      break;
+    }
+
+    FT_FRAME_EXIT();
+
+    if ( !error )
+    {
+      FT_Short   abearing;
+      FT_UShort  aadvance;
+
+
+      tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
+
+      metrics->horiBearingX = originOffsetX;
+      metrics->horiBearingY = -originOffsetY + metrics->height;
+      metrics->horiAdvance  = aadvance * face->root.size->metrics.x_ppem /
+                                face->header.Units_Per_EM;
+    }
+
+    return error;
+  }
+
   FT_LOCAL( FT_Error )
   tt_face_load_sbit_image( TT_Face              face,
                            FT_ULong             strike_index,
@@ -1151,23 +1367,67 @@
                            FT_Bitmap           *map,
                            TT_SBit_MetricsRec  *metrics )
   {
-    TT_SBitDecoderRec  decoder[1];
-    FT_Error           error;
-
-    FT_UNUSED( load_flags );
-    FT_UNUSED( stream );
-    FT_UNUSED( map );
+    FT_Error  error = FT_Err_Ok;
 
 
-    error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
-    if ( !error )
+    switch ( (FT_UInt)face->sbit_table_type )
     {
-      error = tt_sbit_decoder_load_image( decoder,
-                                          load_flags,
-                                          glyph_index,
-                                          0,
-                                          0 );
-      tt_sbit_decoder_done( decoder );
+    case TT_SBIT_TABLE_TYPE_EBLC:
+    case TT_SBIT_TABLE_TYPE_CBLC:
+      {
+        TT_SBitDecoderRec  decoder[1];
+
+
+        error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
+        if ( !error )
+        {
+          error = tt_sbit_decoder_load_image( decoder,
+                                              glyph_index,
+                                              0,
+                                              0 );
+          tt_sbit_decoder_done( decoder );
+        }
+      }
+      break;
+
+    case TT_SBIT_TABLE_TYPE_SBIX:
+      error = tt_face_load_sbix_image( face,
+                                       strike_index,
+                                       glyph_index,
+                                       stream,
+                                       map,
+                                       metrics );
+      break;
+
+    default:
+      error = FT_THROW( Unknown_File_Format );
+      break;
+    }
+
+    /* Flatten color bitmaps if color was not requested. */
+    if ( !error                                &&
+         !( load_flags & FT_LOAD_COLOR )       &&
+         map->pixel_mode == FT_PIXEL_MODE_BGRA )
+    {
+      FT_Bitmap   new_map;
+      FT_Library  library = face->root.glyph->library;
+
+
+      FT_Bitmap_New( &new_map );
+
+      /* Convert to 8bit grayscale. */
+      error = FT_Bitmap_Convert( library, map, &new_map, 1 );
+      if ( error )
+        FT_Bitmap_Done( library, &new_map );
+      else
+      {
+        map->pixel_mode = new_map.pixel_mode;
+        map->pitch      = new_map.pitch;
+        map->num_grays  = new_map.num_grays;
+
+        ft_glyphslot_set_bitmap( face->root.glyph, new_map.buffer );
+        face->root.glyph->internal->flags |= FT_GLYPH_OWN_BITMAP;
+      }
     }
 
     return error;
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index ea0b5f8..695d0d8 100644
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -28,11 +28,11 @@
 
 
   FT_LOCAL( FT_Error )
-  tt_face_load_eblc( TT_Face    face,
+  tt_face_load_sbit( TT_Face    face,
                      FT_Stream  stream );
 
   FT_LOCAL( void )
-  tt_face_free_eblc( TT_Face  face );
+  tt_face_free_sbit( TT_Face  face );
 
 
   FT_LOCAL( FT_Error )
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index d2158e7..2c51e9f 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -24,8 +24,8 @@
   /*                                                                       */
   /* - copy `src/smooth/ftgrays.c' (this file) to your current directory   */
   /*                                                                       */
-  /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
-  /*   same directory                                                      */
+  /* - copy `include/ftimage.h' and `src/smooth/ftgrays.h' to the same     */
+  /*   directory                                                           */
   /*                                                                       */
   /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in        */
   /*                                                                       */
@@ -310,6 +310,40 @@
 #endif
 
 
+  /* Compute `dividend / divisor' and return both its quotient and     */
+  /* remainder, cast to a specific type.  This macro also ensures that */
+  /* the remainder is always positive.                                 */
+#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+  FT_BEGIN_STMNT                                                   \
+    (quotient)  = (type)( (dividend) / (divisor) );                \
+    (remainder) = (type)( (dividend) % (divisor) );                \
+    if ( (remainder) < 0 )                                         \
+    {                                                              \
+      (quotient)--;                                                \
+      (remainder) += (type)(divisor);                              \
+    }                                                              \
+  FT_END_STMNT
+
+#ifdef  __arm__
+  /* Work around a bug specific to GCC which make the compiler fail to */
+  /* optimize a division and modulo operation on the same parameters   */
+  /* into a single call to `__aeabi_idivmod'.  See                     */
+  /*                                                                   */
+  /*  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721                */
+#undef FT_DIV_MOD
+#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+  FT_BEGIN_STMNT                                                   \
+    (quotient)  = (type)( (dividend) / (divisor) );                \
+    (remainder) = (type)( (dividend) - (quotient) * (divisor) );   \
+    if ( (remainder) < 0 )                                         \
+    {                                                              \
+      (quotient)--;                                                \
+      (remainder) += (type)(divisor);                              \
+    }                                                              \
+  FT_END_STMNT
+#endif /* __arm__ */
+
+
   /*************************************************************************/
   /*                                                                       */
   /*   TYPE DEFINITIONS                                                    */
@@ -358,6 +392,14 @@
   } TCell;
 
 
+#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 */
+
   typedef struct  gray_TWorker_
   {
     TCoord  ex, ey;
@@ -405,6 +447,10 @@
 
   } gray_TWorker, *gray_PWorker;
 
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
 
 #ifndef FT_STATIC_RASTER
 #define ras  (*worker)
@@ -536,7 +582,7 @@
   static void
   gray_record_cell( RAS_ARG )
   {
-    if ( !ras.invalid && ( ras.area | ras.cover ) )
+    if ( ras.area | ras.cover )
     {
       PCell  cell = gray_find_cell( RAS_VAR );
 
@@ -585,10 +631,10 @@
 
       ras.area  = 0;
       ras.cover = 0;
+      ras.ex    = ex;
+      ras.ey    = ey;
     }
 
-    ras.ex      = ex;
-    ras.ey      = ey;
     ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
                               ex >= ras.count_ex           );
   }
@@ -674,13 +720,7 @@
       dx    = -dx;
     }
 
-    delta = (TCoord)( p / dx );
-    mod   = (TCoord)( p % dx );
-    if ( mod < 0 )
-    {
-      delta--;
-      mod += (TCoord)dx;
-    }
+    FT_DIV_MOD( TCoord, p, dx, delta, mod );
 
     ras.area  += (TArea)(( fx1 + first ) * delta);
     ras.cover += delta;
@@ -694,14 +734,8 @@
       TCoord  lift, rem;
 
 
-      p    = ONE_PIXEL * ( y2 - y1 + delta );
-      lift = (TCoord)( p / dx );
-      rem  = (TCoord)( p % dx );
-      if ( rem < 0 )
-      {
-        lift--;
-        rem += (TCoord)dx;
-      }
+      p = ONE_PIXEL * ( y2 - y1 + delta );
+      FT_DIV_MOD( TCoord, p, dx, lift, rem );
 
       mod -= (int)dx;
 
@@ -751,9 +785,6 @@
     dx = to_x - ras.x;
     dy = to_y - ras.y;
 
-    /* XXX: we should do something about the trivial case where dx == 0, */
-    /*      as it happens very often!                                    */
-
     /* perform vertical clipping */
     {
       TCoord  min, max;
@@ -832,13 +863,7 @@
       dy    = -dy;
     }
 
-    delta = (int)( p / dy );
-    mod   = (int)( p % dy );
-    if ( mod < 0 )
-    {
-      delta--;
-      mod += (TCoord)dy;
-    }
+    FT_DIV_MOD( int, p, dy, delta, mod );
 
     x = ras.x + delta;
     gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
@@ -849,13 +874,7 @@
     if ( ey1 != ey2 )
     {
       p     = ONE_PIXEL * dx;
-      lift  = (int)( p / dy );
-      rem   = (int)( p % dy );
-      if ( rem < 0 )
-      {
-        lift--;
-        rem += (int)dy;
-      }
+      FT_DIV_MOD( int, p, dy, lift, rem );
       mod -= (int)dy;
 
       while ( ey1 != ey2 )
@@ -1159,7 +1178,8 @@
 
 
     /* record current cell, if any */
-    gray_record_cell( RAS_VAR );
+    if ( !ras.invalid )
+      gray_record_cell( RAS_VAR );
 
     /* start to a new position */
     x = UPSCALE( to->x );
@@ -1769,7 +1789,8 @@
     if ( ft_setjmp( ras.jump_buffer ) == 0 )
     {
       error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
-      gray_record_cell( RAS_VAR );
+      if ( !ras.invalid )
+        gray_record_cell( RAS_VAR );
     }
     else
       error = FT_THROW( Memory_Overflow );
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index fb25706..36d23a2 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -215,7 +215,8 @@
         FT_UShort  ah;
 
 
-        TT_Get_VMetrics( face, start + nn, &tsb, &ah );
+        /* since we don't need `tsb', we use zero for `yMax' parameter */
+        TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah );
         advances[nn] = ah;
       }
     }
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index f640a6c..b10e390 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -85,51 +85,36 @@
   /*************************************************************************/
   /*                                                                       */
   /* Return the vertical metrics in font units for a given glyph.          */
-  /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
-  /* table, typoAscender/Descender from the `OS/2' table would be used     */
-  /* instead, and if there were no `OS/2' table, use ascender/descender    */
-  /* from the `hhea' table.  But that is not what Microsoft's rasterizer   */
-  /* apparently does: It uses the ppem value as the advance height, and    */
-  /* sets the top side bearing to be zero.                                 */
+  /* See macro `TT_LOADER_SET_PP' below for explanations.                  */
   /*                                                                       */
   FT_LOCAL_DEF( void )
   TT_Get_VMetrics( TT_Face     face,
                    FT_UInt     idx,
+                   FT_Pos      yMax,
                    FT_Short*   tsb,
                    FT_UShort*  ah )
   {
     if ( face->vertical_info )
       ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
 
-#if 1             /* Empirically determined, at variance with what MS said */
-
-    else
-    {
-      *tsb = 0;
-      *ah  = face->root.units_per_EM;
-    }
-
-#else      /* This is what MS said to do.  It isn't what they do, however. */
-
     else if ( face->os2.version != 0xFFFFU )
     {
-      *tsb = face->os2.sTypoAscender;
+      *tsb = face->os2.sTypoAscender - yMax;
       *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
     }
+
     else
     {
-      *tsb = face->horizontal.Ascender;
+      *tsb = face->horizontal.Ascender - yMax;
       *ah  = face->horizontal.Ascender - face->horizontal.Descender;
     }
 
-#endif
-
     FT_TRACE5(( "  advance height (font units): %d\n", *ah ));
     FT_TRACE5(( "  top side bearing (font units): %d\n", *tsb ));
   }
 
 
-  static void
+  static FT_Error
   tt_get_metrics( TT_Loader  loader,
                   FT_UInt    glyph_index )
   {
@@ -138,17 +123,28 @@
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
+    FT_Error   error;
+    FT_Stream  stream = loader->stream;
+
     FT_Short   left_bearing = 0, top_bearing = 0;
     FT_UShort  advance_width = 0, advance_height = 0;
 
+    /* we must preserve the stream position          */
+    /* (which gets altered by the metrics functions) */
+    FT_ULong  pos = FT_STREAM_POS();
+
 
     TT_Get_HMetrics( face, glyph_index,
                      &left_bearing,
                      &advance_width );
     TT_Get_VMetrics( face, glyph_index,
+                     loader->bbox.yMax,
                      &top_bearing,
                      &advance_height );
 
+    if ( FT_STREAM_SEEK( pos ) )
+      return error;
+
     loader->left_bearing = left_bearing;
     loader->advance      = advance_width;
     loader->top_bearing  = top_bearing;
@@ -171,6 +167,8 @@
       loader->linear_def = 1;
       loader->linear     = advance_width;
     }
+
+    return FT_Err_Ok;
   }
 
 
@@ -350,9 +348,9 @@
     FT_GlyphLoader  gloader    = load->gloader;
     FT_Int          n_contours = load->n_contours;
     FT_Outline*     outline;
-    TT_Face         face       = (TT_Face)load->face;
     FT_UShort       n_ins;
     FT_Int          n_points;
+    FT_ULong        tmp;
 
     FT_Byte         *flag, *flag_limit;
     FT_Byte         c, count;
@@ -418,14 +416,7 @@
 
     FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
 
-    if ( n_ins > face->max_profile.maxSizeOfInstructions )
-    {
-      FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
-                  n_ins ));
-      error = FT_THROW( Too_Many_Hints );
-      goto Fail;
-    }
-
+    /* check it */
     if ( ( limit - p ) < n_ins )
     {
       FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
@@ -437,6 +428,20 @@
 
     if ( IS_HINTED( load->load_flags ) )
     {
+      /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
+      /* and thus update the bytecode array size by ourselves       */
+
+      tmp   = load->exec->glyphSize;
+      error = Update_Max( load->exec->memory,
+                          &tmp,
+                          sizeof ( FT_Byte ),
+                          (void*)&load->exec->glyphIns,
+                          n_ins );
+
+      load->exec->glyphSize = (FT_UShort)tmp;
+      if ( error )
+        return error;
+
       load->glyph->control_len  = n_ins;
       load->glyph->control_data = load->exec->glyphIns;
 
@@ -733,7 +738,6 @@
 #endif
 
     TT_GlyphZone  zone = &loader->zone;
-    FT_Pos        origin;
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
     FT_UInt       n_ins;
@@ -745,19 +749,12 @@
 #ifdef TT_USE_BYTECODE_INTERPRETER
     if ( loader->glyph->control_len > 0xFFFFL )
     {
-      FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
-      FT_TRACE1(( "(0x%lx byte) is truncated\n",
+      FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
+      FT_TRACE1(( " (0x%lx byte) is truncated\n",
                  loader->glyph->control_len ));
     }
     n_ins = (FT_UInt)( loader->glyph->control_len );
-#endif
 
-    origin = zone->cur[zone->n_points - 4].x;
-    origin = FT_PIX_ROUND( origin ) - origin;
-    if ( origin )
-      translate_array( zone->n_points, zone->cur, origin, 0 );
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
     /* save original point position in org */
     if ( n_ins > 0 )
       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
@@ -783,9 +780,13 @@
     }
 #endif
 
-    /* round pp2 and pp4 */
+    /* round phantom points */
+    zone->cur[zone->n_points - 4].x =
+      FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
     zone->cur[zone->n_points - 3].x =
       FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
+    zone->cur[zone->n_points - 2].y =
+      FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
     zone->cur[zone->n_points - 1].y =
       FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
 
@@ -823,13 +824,10 @@
 #endif
 
     /* save glyph phantom points */
-    if ( !loader->preserve_pps )
-    {
-      loader->pp1 = zone->cur[zone->n_points - 4];
-      loader->pp2 = zone->cur[zone->n_points - 3];
-      loader->pp3 = zone->cur[zone->n_points - 2];
-      loader->pp4 = zone->cur[zone->n_points - 1];
-    }
+    loader->pp1 = zone->cur[zone->n_points - 4];
+    loader->pp2 = zone->cur[zone->n_points - 3];
+    loader->pp3 = zone->cur[zone->n_points - 2];
+    loader->pp4 = zone->cur[zone->n_points - 1];
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -1077,9 +1075,9 @@
       if ( !x && !y )
         return FT_Err_Ok;
 
-  /* Use a default value dependent on                                     */
-  /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
-  /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
+      /* Use a default value dependent on                                  */
+      /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old */
+      /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit.            */
 
       if ( have_scale &&
 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -1091,10 +1089,10 @@
 
 #if 0
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* This algorithm is what Apple documents.  But it doesn't work.         */
-  /*                                                                       */
+        /*******************************************************************/
+        /*                                                                 */
+        /* This algorithm is what Apple documents.  But it doesn't work.   */
+        /*                                                                 */
         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
                                             : -subglyph->transform.xx;
         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
@@ -1114,12 +1112,12 @@
         x = FT_MulFix( x, m );
         y = FT_MulFix( y, n );
 
-#else /* 0 */
+#else /* 1 */
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* This algorithm is a guess and works much better than the above.       */
-  /*                                                                       */
+        /*******************************************************************/
+        /*                                                                 */
+        /* This algorithm is a guess and works much better than the above. */
+        /*                                                                 */
         FT_Fixed  mac_xscale = FT_Hypot( subglyph->transform.xx,
                                          subglyph->transform.xy );
         FT_Fixed  mac_yscale = FT_Hypot( subglyph->transform.yy,
@@ -1129,7 +1127,7 @@
         x = FT_MulFix( x, mac_xscale );
         y = FT_MulFix( y, mac_yscale );
 
-#endif /* 0 */
+#endif /* 1 */
 
       }
 
@@ -1218,21 +1216,23 @@
       max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
       if ( n_ins > max_ins )
       {
-        /* acroread ignores this field, so we only do a rough safety check */
+        /* don't trust `maxSizeOfInstructions'; */
+        /* only do a rough safety check         */
         if ( (FT_Int)n_ins > loader->byte_len )
         {
-          FT_TRACE1(( "TT_Process_Composite_Glyph: "
-                      "too many instructions (%d) for glyph with length %d\n",
+          FT_TRACE1(( "TT_Process_Composite_Glyph:"
+                      " too many instructions (%d) for glyph with length %d\n",
                       n_ins, loader->byte_len ));
           return FT_THROW( Too_Many_Hints );
         }
 
-        tmp = loader->exec->glyphSize;
+        tmp   = loader->exec->glyphSize;
         error = Update_Max( loader->exec->memory,
                             &tmp,
                             sizeof ( FT_Byte ),
                             (void*)&loader->exec->glyphIns,
                             n_ins );
+
         loader->exec->glyphSize = (FT_UShort)tmp;
         if ( error )
           return error;
@@ -1254,7 +1254,7 @@
 
     /* Some points are likely touched during execution of  */
     /* instructions on components.  So let's untouch them. */
-    for ( i = start_point; i < loader->zone.n_points; i++ )
+    for ( i = 0; i < loader->zone.n_points; i++ )
       loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
 
     loader->zone.n_points += 4;
@@ -1263,21 +1263,131 @@
   }
 
 
-  /* Calculate the four phantom points.                     */
-  /* The first two stand for horizontal origin and advance. */
-  /* The last two stand for vertical origin and advance.    */
+  /*
+   * Calculate the phantom points
+   *
+   * Defining the right side bearing (rsb) as
+   *
+   *   rsb = aw - (lsb + xmax - xmin)
+   *
+   * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
+   * and `xmax' the glyph's minimum and maximum x value), the OpenType
+   * specification defines the initial position of horizontal phantom points
+   * as
+   *
+   *   pp1 = (round(xmin - lsb), 0)      ,
+   *   pp2 = (round(pp1 + aw), 0)        .
+   *
+   * Note that the rounding to the grid (in the device space) is not
+   * documented currently in the specification.
+   *
+   * However, the specification lacks the precise definition of vertical
+   * phantom points.  Greg Hitchcock provided the following explanation.
+   *
+   * - a `vmtx' table is present
+   *
+   *   For any glyph, the minimum and maximum y values (`ymin' and `ymax')
+   *   are given in the `glyf' table, the top side bearing (tsb) and advance
+   *   height (ah) are given in the `vmtx' table.  The bottom side bearing
+   *   (bsb) is then calculated as
+   *
+   *     bsb = ah - (tsb + ymax - ymin)       ,
+   *
+   *   and the initial position of vertical phantom points is
+   *
+   *     pp3 = (x, round(ymax + tsb))       ,
+   *     pp4 = (x, round(pp3 - ah))         .
+   *
+   *   See below for value `x'.
+   *
+   * - no `vmtx' table in the font
+   *
+   *   If there is an `OS/2' table, we set
+   *
+   *     DefaultAscender = sTypoAscender       ,
+   *     DefaultDescender = sTypoDescender     ,
+   *
+   *   otherwise we use data from the `hhea' table:
+   *
+   *     DefaultAscender = Ascender         ,
+   *     DefaultDescender = Descender       .
+   *
+   *   With these two variables we can now set
+   *
+   *     ah = DefaultAscender - sDefaultDescender    ,
+   *     tsb = DefaultAscender - yMax                ,
+   *
+   *   and proceed as if a `vmtx' table was present.
+   *
+   * Usually we have
+   *
+   *   x = aw / 2      ,                                                (1)
+   *
+   * but there is one compatibility case where it can be set to
+   *
+   *   x = -DefaultDescender -
+   *         ((DefaultAscender - DefaultDescender - aw) / 2)     .      (2)
+   *
+   * and another one with
+   *
+   *   x = 0     .                                                      (3)
+   *
+   * In Windows, the history of those values is quite complicated,
+   * depending on the hinting engine (that is, the graphics framework).
+   *
+   *   framework        from                 to       formula
+   *  ----------------------------------------------------------
+   *    GDI       Windows 98               current      (1)
+   *              (Windows 2000 for NT)
+   *    GDI+      Windows XP               Windows 7    (2)
+   *    GDI+      Windows 8                current      (3)
+   *    DWrite    Windows 7                current      (3)
+   *
+   * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
+   * (3) for everything else.
+   *
+   */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
 #define TT_LOADER_SET_PP( loader )                                          \
-          do {                                                              \
+          do                                                                \
+          {                                                                 \
+            FT_Bool  subpixel_  = loader->exec ? loader->exec->subpixel     \
+                                               : 0;                         \
+            FT_Bool  grayscale_ = loader->exec ? loader->exec->grayscale    \
+                                               : 0;                         \
+            FT_Bool  use_aw_2_  = (FT_Bool)( subpixel_ && grayscale_ );     \
+                                                                            \
+                                                                            \
             (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
             (loader)->pp1.y = 0;                                            \
             (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
             (loader)->pp2.y = 0;                                            \
+                                                                            \
+            (loader)->pp3.x = use_aw_2_ ? (loader)->advance / 2 : 0;        \
+            (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing;  \
+            (loader)->pp4.x = use_aw_2_ ? (loader)->advance / 2 : 0;        \
+            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
+          } while ( 0 )
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+#define TT_LOADER_SET_PP( loader )                                          \
+          do                                                                \
+          {                                                                 \
+            (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
+            (loader)->pp1.y = 0;                                            \
+            (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
+            (loader)->pp2.y = 0;                                            \
+                                                                            \
             (loader)->pp3.x = 0;                                            \
-            (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  \
+            (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing;  \
             (loader)->pp4.x = 0;                                            \
             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
           } while ( 0 )
 
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -1341,8 +1451,6 @@
       y_scale = 0x10000L;
     }
 
-    tt_get_metrics( loader, glyph_index );
-
     /* Set `offset' to the start of the glyph relative to the start of */
     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
     /* bytes.                                                          */
@@ -1402,7 +1510,17 @@
 
       /* read glyph header first */
       error = face->read_glyph_header( loader );
-      if ( error || header_only )
+      if ( error )
+        goto Exit;
+
+      /* the metrics must be computed after loading the glyph header */
+      /* since we need the glyph's `yMax' value in case the vertical */
+      /* metrics must be emulated                                    */
+      error = tt_get_metrics( loader, glyph_index );
+      if ( error )
+        goto Exit;
+
+      if ( header_only )
         goto Exit;
     }
 
@@ -1413,6 +1531,10 @@
       loader->bbox.yMin = 0;
       loader->bbox.yMax = 0;
 
+      error = tt_get_metrics( loader, glyph_index );
+      if ( error )
+        goto Exit;
+
       if ( header_only )
         goto Exit;
 
@@ -1437,21 +1559,32 @@
         if ( error )
           goto Exit;
 
-        loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
-        loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
-        loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
-        loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
+        loader->pp1.x += deltas[0].x;
+        loader->pp1.y += deltas[0].y;
+        loader->pp2.x += deltas[1].x;
+        loader->pp2.y += deltas[1].y;
+
+        loader->pp3.x += deltas[2].x;
+        loader->pp3.y += deltas[2].y;
+        loader->pp4.x += deltas[3].x;
+        loader->pp4.y += deltas[3].y;
 
         FT_FREE( deltas );
       }
 
-#endif
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
+      /* scale phantom points, if necessary; */
+      /* they get rounded in `TT_Hint_Glyph' */
       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
       {
         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+        /* pp1.y and pp2.y are always zero */
+
+        loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+        loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
       }
 
@@ -1459,8 +1592,8 @@
       goto Exit;
     }
 
-    /* must initialize points before (possibly) overriding */
-    /* glyph metrics from the incremental interface        */
+    /* must initialize phantom points before (possibly) overriding */
+    /* glyph metrics from the incremental interface                */
     TT_LOADER_SET_PP( loader );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -1533,7 +1666,7 @@
                          face,
                          glyph_index,
                          &deltas,
-                         gloader->current.num_subglyphs + 4 )) != 0 )
+                         gloader->current.num_subglyphs + 4 ) ) != 0 )
           goto Exit;
 
         subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
@@ -1551,21 +1684,32 @@
           }
         }
 
-        loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
-        loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
-        loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
-        loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
+        loader->pp1.x += deltas[i + 0].x;
+        loader->pp1.y += deltas[i + 0].y;
+        loader->pp2.x += deltas[i + 1].x;
+        loader->pp2.y += deltas[i + 1].y;
+
+        loader->pp3.x += deltas[i + 2].x;
+        loader->pp3.y += deltas[i + 2].y;
+        loader->pp4.x += deltas[i + 3].x;
+        loader->pp4.y += deltas[i + 3].y;
 
         FT_FREE( deltas );
       }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
+      /* scale phantom points, if necessary; */
+      /* they get rounded in `TT_Hint_Glyph' */
       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
       {
         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+        /* pp1.y and pp2.y are always zero */
+
+        loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+        loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
       }
 
@@ -1625,6 +1769,7 @@
           /* restore subglyph pointer */
           subglyph = gloader->base.subglyphs + num_base_subgs + n;
 
+          /* restore phantom points if necessary */
           if ( !( subglyph->flags & USE_MY_METRICS ) )
           {
             loader->pp1 = pp[0];
@@ -1961,8 +2106,7 @@
 #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;
+      FT_Bool  subpixel = FALSE;
 
 #if 0
       /* not used yet */
@@ -1995,24 +2139,24 @@
 
       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             );
+        subpixel = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
+                              FT_RENDER_MODE_MONO               )  &&
+                            SPH_OPTION_SET_SUBPIXEL                );
 
-        if ( subpixel_hinting )
-          grayscale = grayscale_hinting = FALSE;
+        if ( subpixel )
+          grayscale = FALSE;
         else if ( SPH_OPTION_SET_GRAYSCALE )
         {
-          grayscale = grayscale_hinting = TRUE;
-          subpixel_hinting              = FALSE;
+          grayscale = TRUE;
+          subpixel  = FALSE;
         }
         else
-          grayscale = grayscale_hinting = FALSE;
+          grayscale = FALSE;
 
         if ( FT_IS_TRICKY( glyph->face ) )
-          subpixel_hinting = grayscale_hinting = FALSE;
+          subpixel = FALSE;
 
-        exec->ignore_x_mode      = subpixel_hinting || grayscale_hinting;
+        exec->ignore_x_mode      = subpixel || grayscale;
         exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
         if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
           exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
@@ -2055,24 +2199,24 @@
       {
         /* a change from mono to subpixel rendering (and vice versa) */
         /* requires a re-execution of the CVT program                */
-        if ( subpixel_hinting != exec->subpixel_hinting )
+        if ( subpixel != exec->subpixel )
         {
           FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
                       " re-executing `prep' table\n" ));
 
-          exec->subpixel_hinting = subpixel_hinting;
-          reexecute              = TRUE;
+          exec->subpixel = subpixel;
+          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 )
+        if ( grayscale != exec->grayscale )
         {
           FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
                       " re-executing `prep' table\n" ));
 
-          exec->grayscale_hinting = grayscale_hinting;
-          reexecute               = TRUE;
+          exec->grayscale = grayscale;
+          reexecute       = TRUE;
         }
       }
       else
@@ -2204,6 +2348,8 @@
 
     error = FT_Err_Ok;
 
+    FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
+
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
     /* try to load embedded bitmap if any              */
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 05f7588..3f1699e 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -43,6 +43,7 @@
   FT_LOCAL( void )
   TT_Get_VMetrics( TT_Face     face,
                    FT_UInt     idx,
+                   FT_Pos      yMax,
                    FT_Short*   tsb,
                    FT_UShort*  ah );
 
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 798d4a9..3f110c2 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -1437,8 +1437,107 @@
 
 #undef PACK
 
-#if 1
 
+#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+
+#if defined( __arm__ )                                 && \
+    ( defined( __thumb2__ ) || !defined( __thumb__ ) )
+
+#define TT_MulFix14  TT_MulFix14_arm
+
+  static FT_Int32
+  TT_MulFix14_arm( FT_Int32  a,
+                   FT_Int    b )
+  {
+    register FT_Int32  t, t2;
+
+
+#if defined( __CC_ARM ) || defined( __ARMCC__ )
+
+    __asm
+    {
+      smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
+      mov   a,  t,  asr #31         /* a   = (hi >> 31) */
+      add   a,  a,  #0x2000         /* a  += 0x2000 */
+      adds  t2, t2, a               /* t2 += a */
+      adc   t,  t,  #0              /* t  += carry */
+      mov   a,  t2, lsr #14         /* a   = t2 >> 14 */
+      orr   a,  a,  t,  lsl #18     /* a  |= t << 18 */
+    }
+
+#elif defined( __GNUC__ )
+
+    __asm__ __volatile__ (
+      "smull  %1, %2, %4, %3\n\t"       /* (lo=%1,hi=%2) = a*b */
+      "mov    %0, %2, asr #31\n\t"      /* %0  = (hi >> 31) */
+#ifdef __clang__
+      "add.w  %0, %0, #0x2000\n\t"      /* %0 += 0x2000 */
+#else
+      "add    %0, %0, #0x2000\n\t"      /* %0 += 0x2000 */
+#endif
+      "adds   %1, %1, %0\n\t"           /* %1 += %0 */
+      "adc    %2, %2, #0\n\t"           /* %2 += carry */
+      "mov    %0, %1, lsr #14\n\t"      /* %0  = %1 >> 16 */
+      "orr    %0, %0, %2, lsl #18\n\t"  /* %0 |= %2 << 16 */
+      : "=r"(a), "=&r"(t2), "=&r"(t)
+      : "r"(a), "r"(b)
+      : "cc" );
+
+#endif
+
+    return a;
+  }
+
+#endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */
+
+#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+
+#if defined( __GNUC__ )                              && \
+    ( defined( __i386__ ) || defined( __x86_64__ ) )
+
+#define TT_MulFix14  TT_MulFix14_long_long
+
+  /* Temporarily disable the warning that C90 doesn't support `long long'. */
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wlong-long"
+
+  /* This is declared `noinline' because inlining the function results */
+  /* in slower code.  The `pure' attribute indicates that the result   */
+  /* only depends on the parameters.                                   */
+  static __attribute__(( noinline ))
+         __attribute__(( pure )) FT_Int32
+  TT_MulFix14_long_long( FT_Int32  a,
+                         FT_Int    b )
+  {
+
+    long long  ret = (long long)a * b;
+
+    /* The following line assumes that right shifting of signed values */
+    /* will actually preserve the sign bit.  The exact behaviour is    */
+    /* undefined, but this is true on x86 and x86_64.                  */
+    long long  tmp = ret >> 63;
+
+
+    ret += 0x2000 + tmp;
+
+    return (FT_Int32)( ret >> 14 );
+  }
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic pop
+#endif
+
+#endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */
+
+
+#ifndef TT_MulFix14
+
+  /* Compute (a*b)/2^14 with maximum accuracy and rounding.  */
+  /* This is optimized to be faster than calling FT_MulFix() */
+  /* for platforms where sizeof(int) == 2.                   */
   static FT_Int32
   TT_MulFix14( FT_Int32  a,
                FT_Int    b )
@@ -1470,37 +1569,50 @@
     return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
   }
 
-#else
+#endif  /* !TT_MulFix14 */
 
-  /* compute (a*b)/2^14 with maximum accuracy and rounding */
-  static FT_Int32
-  TT_MulFix14( FT_Int32  a,
-               FT_Int    b )
+
+#if defined( __GNUC__ )        && \
+    ( defined( __i386__ )   ||    \
+      defined( __x86_64__ ) ||    \
+      defined( __arm__ )    )
+
+#define TT_DotFix14  TT_DotFix14_long_long
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wlong-long"
+
+  static __attribute__(( pure )) FT_Int32
+  TT_DotFix14_long_long( FT_Int32  ax,
+                         FT_Int32  ay,
+                         FT_Int    bx,
+                         FT_Int    by )
   {
-    FT_Int32   m, s, hi;
-    FT_UInt32  l, lo;
+    /* Temporarily disable the warning that C90 doesn't support */
+    /* `long long'.                                             */
+
+    long long  temp1 = (long long)ax * bx;
+    long long  temp2 = (long long)ay * by;
 
 
-    /* compute ax*bx as 64-bit value */
-    l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
-    m  = ( a >> 16 ) * b;
+    temp1 += temp2;
+    temp2  = temp1 >> 63;
+    temp1 += 0x2000 + temp2;
 
-    lo = l + ( (FT_UInt32)m << 16 );
-    hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
+    return (FT_Int32)( temp1 >> 14 );
 
-    /* divide the result by 2^14 with rounding */
-    s   = hi >> 31;
-    l   = lo + (FT_UInt32)s;
-    hi += s + ( l < lo );
-    lo  = l;
-
-    l   = lo + 0x2000U;
-    hi += l < lo;
-
-    return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
   }
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic pop
 #endif
 
+#endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */
+
+
+#ifndef TT_DotFix14
 
   /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
   static FT_Int32
@@ -1543,6 +1655,8 @@
     return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
   }
 
+#endif /* TT_DotFix14 */
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -3037,42 +3151,42 @@
   }
 
 
-#define DO_JROT                                                   \
-    if ( args[1] != 0 )                                           \
-    {                                                             \
-      if ( args[0] == 0 && CUR.args == 0 )                        \
-        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 = FT_THROW( Bad_Argument );                     \
-      CUR.step_ins = FALSE;                                       \
+#define DO_JROT                                                    \
+    if ( args[1] != 0 )                                            \
+    {                                                              \
+      if ( args[0] == 0 && CUR.args == 0 )                         \
+        CUR.error = FT_THROW( Bad_Argument );                      \
+      CUR.IP += args[0];                                           \
+      if ( CUR.IP < 0                                           || \
+           ( CUR.callTop > 0                                  &&   \
+             CUR.IP > CUR.callStack[CUR.callTop - 1].Def->end ) )  \
+        CUR.error = FT_THROW( Bad_Argument );                      \
+      CUR.step_ins = FALSE;                                        \
     }
 
 
-#define DO_JMPR                                                 \
-    if ( args[0] == 0 && CUR.args == 0 )                        \
-      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 = FT_THROW( Bad_Argument );                     \
+#define DO_JMPR                                                  \
+    if ( args[0] == 0 && CUR.args == 0 )                         \
+      CUR.error = FT_THROW( Bad_Argument );                      \
+    CUR.IP += args[0];                                           \
+    if ( CUR.IP < 0                                           || \
+         ( CUR.callTop > 0                                  &&   \
+           CUR.IP > CUR.callStack[CUR.callTop - 1].Def->end ) )  \
+      CUR.error = FT_THROW( Bad_Argument );                      \
     CUR.step_ins = FALSE;
 
 
-#define DO_JROF                                                   \
-    if ( args[1] == 0 )                                           \
-    {                                                             \
-      if ( args[0] == 0 && CUR.args == 0 )                        \
-        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 = FT_THROW( Bad_Argument );                     \
-      CUR.step_ins = FALSE;                                       \
+#define DO_JROF                                                    \
+    if ( args[1] == 0 )                                            \
+    {                                                              \
+      if ( args[0] == 0 && CUR.args == 0 )                         \
+        CUR.error = FT_THROW( Bad_Argument );                      \
+      CUR.IP += args[0];                                           \
+      if ( CUR.IP < 0                                           || \
+           ( CUR.callTop > 0                                  &&   \
+             CUR.IP > CUR.callStack[CUR.callTop - 1].Def->end ) )  \
+        CUR.error = FT_THROW( Bad_Argument );                      \
+      CUR.step_ins = FALSE;                                        \
     }
 
 
@@ -4788,7 +4902,7 @@
     if ( pRec->Cur_Count > 0 )
     {
       CUR.callTop++;
-      CUR.IP = pRec->Cur_Restart;
+      CUR.IP = pRec->Def->start;
     }
     else
       /* Loop through the current function */
@@ -4878,8 +4992,7 @@
     pCrec->Caller_Range = CUR.curRange;
     pCrec->Caller_IP    = CUR.IP + 1;
     pCrec->Cur_Count    = 1;
-    pCrec->Cur_Restart  = def->start;
-    pCrec->Cur_End      = def->end;
+    pCrec->Def          = def;
 
     CUR.callTop++;
 
@@ -4967,8 +5080,7 @@
       pCrec->Caller_Range = CUR.curRange;
       pCrec->Caller_IP    = CUR.IP + 1;
       pCrec->Cur_Count    = (FT_Int)args[0];
-      pCrec->Cur_Restart  = def->start;
-      pCrec->Cur_End      = def->end;
+      pCrec->Def          = def;
 
       CUR.callTop++;
 
@@ -6173,7 +6285,7 @@
     FT_F26Dot6  distance;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    FT_F26Dot6  control_value_cutin;
+    FT_F26Dot6  control_value_cutin = 0; /* pacify compiler */
 
 
     if ( SUBPIXEL_HINTING )
@@ -6542,8 +6654,8 @@
                 control_value_cutin,
                 minimum_distance;
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    FT_Int      B1;
-    FT_Int      B2;
+    FT_Int      B1           = 0; /* pacify compiler */
+    FT_Int      B2           = 0;
     FT_Bool     reverse_move = FALSE;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
@@ -7708,26 +7820,16 @@
          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 )
+      if ( CUR.rasterizer_version >= 37 )
       {
-        K |= 1 << 13;
-
-        /* the stuff below is irrelevant if subpixel_hinting is not set */
+        /********************************/
+        /* HINTING FOR SUBPIXEL         */
+        /* Selector Bit:  6             */
+        /* Return Bit(s): 13            */
+        /*                              */
+        if ( ( args[0] & 64 ) != 0 && CUR.subpixel )
+          K |= 1 << 13;
 
         /********************************/
         /* COMPATIBLE WIDTHS ENABLED    */
@@ -7803,8 +7905,7 @@
         call->Caller_Range = CUR.curRange;
         call->Caller_IP    = CUR.IP + 1;
         call->Cur_Count    = 1;
-        call->Cur_Restart  = def->start;
-        call->Cur_End      = def->end;
+        call->Def          = def;
 
         INS_Goto_CodeRange( def->range, def->start );
 
@@ -8860,8 +8961,7 @@
                 callrec->Caller_Range = CUR.curRange;
                 callrec->Caller_IP    = CUR.IP + 1;
                 callrec->Cur_Count    = 1;
-                callrec->Cur_Restart  = def->start;
-                callrec->Cur_End      = def->end;
+                callrec->Def          = def;
 
                 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
                   goto LErrorLabel_;
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 69f5011..1d8825d 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -101,8 +101,8 @@
     FT_Int   Caller_Range;
     FT_Long  Caller_IP;
     FT_Long  Cur_Count;
-    FT_Long  Cur_Restart;
-    FT_Long  Cur_End;
+
+    TT_DefRecord  *Def; /* either FDEF or IDEF */
 
   } TT_CallRec, *TT_CallStack;
 
@@ -263,12 +263,10 @@
 #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            subpixel;          /* Using subpixel hinting?       */
     FT_Bool            ignore_x_mode;     /* Standard rendering mode for   */
                                           /* subpixel hinting.  On if gray */
-                                          /* or subpixel hinting is on )   */
+                                          /* or subpixel hinting is on.    */
 
     /* The following 4 aren't fully implemented but here for MS rasterizer */
     /* compatibility.                                                      */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 7897efa..4adba58 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -150,20 +150,21 @@
   tt_check_trickyness_family( FT_String*  name )
   {
 
-#define TRICK_NAMES_MAX_CHARACTERS  16
-#define TRICK_NAMES_COUNT            8
+#define TRICK_NAMES_MAX_CHARACTERS  19
+#define TRICK_NAMES_COUNT            9
 
     static const char trick_names[TRICK_NAMES_COUNT]
                                  [TRICK_NAMES_MAX_CHARACTERS + 1] =
     {
-      "DFKaiSho-SB",     /* dfkaisb.ttf */
+      "DFKaiSho-SB",        /* dfkaisb.ttf */
       "DFKaiShu",
-      "DFKai-SB",        /* kaiu.ttf */
-      "HuaTianKaiTi?",   /* htkt2.ttf */
-      "HuaTianSongTi?",  /* htst3.ttf */
-      "MingLiU",         /* mingliu.ttf & mingliu.ttc */
-      "PMingLiU",        /* mingliu.ttc */
-      "MingLi43",        /* mingli.ttf */
+      "DFKai-SB",           /* kaiu.ttf */
+      "HuaTianKaiTi?",      /* htkt2.ttf */
+      "HuaTianSongTi?",     /* htst3.ttf */
+      "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */
+      "MingLiU",            /* mingliu.ttf & mingliu.ttc */
+      "PMingLiU",           /* mingliu.ttc */
+      "MingLi43",           /* mingli.ttf */
     };
 
     int  nn;
@@ -532,6 +533,10 @@
 
     /* check that we have a valid TrueType file */
     error = sfnt->init_face( stream, face, face_index, num_params, params );
+
+    /* Stream may have changed. */
+    stream = face->root.stream;
+
     if ( error )
       goto Exit;