Merge commit '055aee28cedc3' into klp-dev: am: 2051465f2e am: d7cab14288 am: cafd00b375 am: 4cea75b987
am: fb5baf6521

Change-Id: I2e7c4296eba364189e741b7d61a7ff8bd747d127
diff --git a/Android.mk b/Android.mk
index 2010736..4a6df0a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,10 +1,10 @@
 # this is now the default FreeType build for Android
 #
 ifndef USE_FREETYPE
-USE_FREETYPE := 2.4.2
+USE_FREETYPE := 2.7
 endif
 
-ifeq ($(USE_FREETYPE),2.4.2)
+ifeq ($(USE_FREETYPE),2.7)
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -14,33 +14,33 @@
 LOCAL_ARM_MODE := arm
 
 LOCAL_SRC_FILES:= \
-	src/base/ftbbox.c \
-	src/base/ftbitmap.c \
-	src/base/ftfstype.c \
-	src/base/ftglyph.c \
-	src/base/ftlcdfil.c \
-	src/base/ftstroke.c \
-	src/base/fttype1.c \
-	src/base/ftxf86.c \
-	src/base/ftbase.c \
-	src/base/ftsystem.c \
-	src/base/ftinit.c \
-	src/base/ftgasp.c \
-	src/gzip/ftgzip.c \
-	src/raster/raster.c \
-	src/sfnt/sfnt.c \
-	src/smooth/smooth.c \
-	src/autofit/autofit.c \
-	src/truetype/truetype.c \
-	src/cff/cff.c \
-	src/psnames/psnames.c \
-	src/pshinter/pshinter.c
+    src/base/ftbbox.c \
+    src/base/ftbitmap.c \
+    src/base/ftfntfmt.c \
+    src/base/ftfstype.c \
+    src/base/ftglyph.c \
+    src/base/ftlcdfil.c \
+    src/base/ftstroke.c \
+    src/base/fttype1.c \
+    src/base/ftbase.c \
+    src/base/ftsystem.c \
+    src/base/ftinit.c \
+    src/base/ftgasp.c \
+    src/base/ftmm.c \
+    src/gzip/ftgzip.c \
+    src/raster/raster.c \
+    src/sfnt/sfnt.c \
+    src/smooth/smooth.c \
+    src/autofit/autofit.c \
+    src/truetype/truetype.c \
+    src/cff/cff.c \
+    src/psnames/psnames.c \
+    src/pshinter/pshinter.c
 
 LOCAL_C_INCLUDES += \
-	$(LOCAL_PATH)/builds \
-	$(LOCAL_PATH)/include \
-	external/libpng \
-	external/zlib
+    $(LOCAL_PATH)/include \
+    external/libpng \
+    external/zlib
 
 LOCAL_CFLAGS += -W -Wall
 LOCAL_CFLAGS += -fPIC -DPIC
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b6..b9cafef 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -47,3 +47,5 @@
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libft2_*)
diff --git a/NOTICE b/NOTICE
index 9d114a1..4860cca 100644
--- a/NOTICE
+++ b/NOTICE
@@ -52,7 +52,7 @@
   encourage you to use the following text:
 
    """  
-    Portions of this software are copyright © <year> The FreeType
+    Portions of this software are copyright © <year> The FreeType
     Project (www.freetype.org).  All rights reserved.
    """
 
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..3f599a0
--- /dev/null
+++ b/README.android
@@ -0,0 +1,21 @@
+Freetype
+
+The following modules are disabled in include/freetype/config/ftmodule.h:
+  t1
+  t1cid
+  pfr
+  t42
+  winfnt
+  pcf
+  psaux
+  bdf
+
+The following options are disabled in include/freetype/config/ftoption.h:
+
+  FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+  FT_CONFIG_OPTION_INCREMENTAL
+  TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+The following option is enabled to support color fonts.
+
+  FT_CONFIG_OPTION_USE_PNG
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..6d57025
--- /dev/null
+++ b/README.version
@@ -0,0 +1,3 @@
+URL: http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=c38be52b
+Version: c38be52bf8de3b1699d74932b849bf150265819e (2.7 + update)
+BugComponent: 75970
diff --git a/builds/ft2unix.h b/builds/ft2unix.h
deleted file mode 100644
index 6a3b8d9..0000000
--- a/builds/ft2unix.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ft2build.h                                                             */
-/*                                                                         */
-/*    Build macros of the FreeType 2 library.                              */
-/*                                                                         */
-/*  Copyright 1996-2001, 2003, 2006 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 is a Unix-specific version of <ft2build.h> that should be used   */
-  /* exclusively *after* installation of the library.                      */
-  /*                                                                       */
-  /* It assumes that `/usr/local/include/freetype2' (or whatever is        */
-  /* returned by the `freetype-config --cflags' or `pkg-config --cflags'   */
-  /* command) is in your compilation include path.                         */
-  /*                                                                       */
-  /* We don't need to do anything special in this release.  However, for   */
-  /* a future FreeType 2 release, the following installation changes will  */
-  /* be performed:                                                         */
-  /*                                                                       */
-  /*   - The contents of `freetype-2.x/include/freetype' will be installed */
-  /*     to `/usr/local/include/freetype2' instead of                      */
-  /*     `/usr/local/include/freetype2/freetype'.                          */
-  /*                                                                       */
-  /*   - This file will #include <freetype2/config/ftheader.h>, instead    */
-  /*     of <freetype/config/ftheader.h>.                                  */
-  /*                                                                       */
-  /*   - The contents of `ftheader.h' will be processed with `sed' to      */
-  /*     replace all `<freetype/xxx>' with `<freetype2/xxx>'.              */
-  /*                                                                       */
-  /*   - Adding `/usr/local/include/freetype2' to your compilation include */
-  /*     path will not be necessary anymore.                               */
-  /*                                                                       */
-  /* These changes will be transparent to client applications which use    */
-  /* freetype-config (or pkg-config).  No modifications will be necessary  */
-  /* to compile with the new scheme.                                       */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#ifndef __FT2_BUILD_UNIX_H__
-#define __FT2_BUILD_UNIX_H__
-
-  /* `<prefix>/include/freetype2' must be in your current inclusion path */
-#include <freetype/config/ftheader.h>
-
-#endif /* __FT2_BUILD_UNIX_H__ */
-
-
-/* END */
diff --git a/include/config/ftconfig.h b/include/freetype/config/ftconfig.h
similarity index 92%
rename from include/config/ftconfig.h
rename to include/freetype/config/ftconfig.h
index 89a0f8f..157a704 100644
--- a/include/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific configuration file (specification only).               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2008, 2010-2011, 2013, 2014 by               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -35,8 +35,8 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __FTCONFIG_H__
-#define __FTCONFIG_H__
+#ifndef FTCONFIG_H_
+#define FTCONFIG_H_
 
 #include <ft2build.h>
 #include FT_CONFIG_OPTIONS_H
@@ -266,6 +266,21 @@
 #define FT_INT64   long
 #define FT_UINT64  unsigned long
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* A 64-bit data type may create compilation problems if you compile     */
+  /* in strict ANSI mode.  To avoid them, we disable other 64-bit data     */
+  /* types if __STDC__ is defined.  You can however ignore this rule       */
+  /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro.     */
+  /*                                                                       */
+#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
+
+#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
+
+#define FT_LONG64
+#define FT_INT64   long long int
+#define FT_UINT64  unsigned long long int
+
 #elif defined( _MSC_VER ) && _MSC_VER >= 900  /* Visual C++ (and Intel C++) */
 
   /* this compiler provides the __int64 type */
@@ -300,39 +315,38 @@
 #define FT_INT64   long long int
 #define FT_UINT64  unsigned long long int
 
+#endif /* __STDC_VERSION__ >= 199901L */
+
 #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
 
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* A 64-bit data type will create compilation problems if you compile    */
-  /* in strict ANSI mode.  To avoid them, we disable its use if __STDC__   */
-  /* is defined.  You can however ignore this rule by defining the         */
-  /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro.                     */
-  /*                                                                       */
-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
-
-#ifdef __STDC__
-
-  /* undefine the 64-bit macros in strict ANSI compilation mode */
-#undef FT_LONG64
-#undef FT_INT64
-
-#endif /* __STDC__ */
-
-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
-
 #ifdef FT_LONG64
   typedef FT_INT64   FT_Int64;
   typedef FT_UINT64  FT_UInt64;
 #endif
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* miscellaneous                                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
 #define FT_BEGIN_STMNT  do {
 #define FT_END_STMNT    } while ( 0 )
 #define FT_DUMMY_STMNT  FT_BEGIN_STMNT FT_END_STMNT
 
 
+  /* typeof condition taken from gnulib's `intprops.h' header file */
+#if ( __GNUC__ >= 2                         || \
+      defined( __IBM__TYPEOF__ )            || \
+      ( __SUNPRO_C >= 0x5110 && !__STDC__ ) )
+#define FT_TYPEOF( type )  (__typeof__ (type))
+#else
+#define FT_TYPEOF( type )  /* empty */
+#endif
+
+
 #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
 
 #define FT_LOCAL( x )      static  x
@@ -453,7 +467,7 @@
 FT_END_HEADER
 
 
-#endif /* __FTCONFIG_H__ */
+#endif /* FTCONFIG_H_ */
 
 
 /* END */
diff --git a/include/config/ftheader.h b/include/freetype/config/ftheader.h
similarity index 87%
rename from include/config/ftheader.h
rename to include/freetype/config/ftheader.h
index b623629..68e1483 100644
--- a/include/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Build macros of the FreeType 2 library.                              */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010, 2012, 2013 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -15,8 +15,8 @@
 /*                                                                         */
 /***************************************************************************/
 
-#ifndef __FT_HEADER_H__
-#define __FT_HEADER_H__
+#ifndef FTHEADER_H_
+#define FTHEADER_H_
 
 
   /*@***********************************************************************/
@@ -107,7 +107,7 @@
    *
    */
 #ifndef FT_CONFIG_CONFIG_H
-#define FT_CONFIG_CONFIG_H  <config/ftconfig.h>
+#define FT_CONFIG_CONFIG_H  <freetype/config/ftconfig.h>
 #endif
 
 
@@ -122,7 +122,7 @@
    *
    */
 #ifndef FT_CONFIG_STANDARD_LIBRARY_H
-#define FT_CONFIG_STANDARD_LIBRARY_H  <config/ftstdlib.h>
+#define FT_CONFIG_STANDARD_LIBRARY_H  <freetype/config/ftstdlib.h>
 #endif
 
 
@@ -137,7 +137,7 @@
    *
    */
 #ifndef FT_CONFIG_OPTIONS_H
-#define FT_CONFIG_OPTIONS_H  <config/ftoption.h>
+#define FT_CONFIG_OPTIONS_H  <freetype/config/ftoption.h>
 #endif
 
 
@@ -153,7 +153,7 @@
    *
    */
 #ifndef FT_CONFIG_MODULES_H
-#define FT_CONFIG_MODULES_H  <config/ftmodule.h>
+#define FT_CONFIG_MODULES_H  <freetype/config/ftmodule.h>
 #endif
 
   /* */
@@ -170,7 +170,7 @@
    *   base FreeType~2 API.
    *
    */
-#define FT_FREETYPE_H  <freetype.h>
+#define FT_FREETYPE_H  <freetype/freetype.h>
 
 
   /*************************************************************************
@@ -185,7 +185,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_ERRORS_H  <fterrors.h>
+#define FT_ERRORS_H  <freetype/fterrors.h>
 
 
   /*************************************************************************
@@ -198,7 +198,7 @@
    *   list of FreeType~2 module error offsets (and messages).
    *
    */
-#define FT_MODULE_ERRORS_H  <ftmoderr.h>
+#define FT_MODULE_ERRORS_H  <freetype/ftmoderr.h>
 
 
   /*************************************************************************
@@ -214,7 +214,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_SYSTEM_H  <ftsystem.h>
+#define FT_SYSTEM_H  <freetype/ftsystem.h>
 
 
   /*************************************************************************
@@ -230,7 +230,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_IMAGE_H  <ftimage.h>
+#define FT_IMAGE_H  <freetype/ftimage.h>
 
 
   /*************************************************************************
@@ -245,7 +245,7 @@
    *   It is included by @FT_FREETYPE_H.
    *
    */
-#define FT_TYPES_H  <fttypes.h>
+#define FT_TYPES_H  <freetype/fttypes.h>
 
 
   /*************************************************************************
@@ -260,7 +260,7 @@
    *   (Most applications will never need to include this file.)
    *
    */
-#define FT_LIST_H  <ftlist.h>
+#define FT_LIST_H  <freetype/ftlist.h>
 
 
   /*************************************************************************
@@ -273,7 +273,7 @@
    *   scalable outline management API of FreeType~2.
    *
    */
-#define FT_OUTLINE_H  <ftoutln.h>
+#define FT_OUTLINE_H  <freetype/ftoutln.h>
 
 
   /*************************************************************************
@@ -286,7 +286,7 @@
    *   API which manages multiple @FT_Size objects per face.
    *
    */
-#define FT_SIZES_H  <ftsizes.h>
+#define FT_SIZES_H  <freetype/ftsizes.h>
 
 
   /*************************************************************************
@@ -299,7 +299,7 @@
    *   module management API of FreeType~2.
    *
    */
-#define FT_MODULE_H  <ftmodapi.h>
+#define FT_MODULE_H  <freetype/ftmodapi.h>
 
 
   /*************************************************************************
@@ -312,7 +312,7 @@
    *   renderer module management API of FreeType~2.
    *
    */
-#define FT_RENDER_H  <ftrender.h>
+#define FT_RENDER_H  <freetype/ftrender.h>
 
 
   /*************************************************************************
@@ -325,7 +325,7 @@
    *   structures and macros related to the auto-hinting module.
    *
    */
-#define FT_AUTOHINTER_H  <ftautoh.h>
+#define FT_AUTOHINTER_H  <freetype/ftautoh.h>
 
 
   /*************************************************************************
@@ -338,7 +338,7 @@
    *   structures and macros related to the CFF driver module.
    *
    */
-#define FT_CFF_DRIVER_H  <ftcffdrv.h>
+#define FT_CFF_DRIVER_H  <freetype/ftcffdrv.h>
 
 
   /*************************************************************************
@@ -351,7 +351,7 @@
    *   structures and macros related to the TrueType driver module.
    *
    */
-#define FT_TRUETYPE_DRIVER_H  <ftttdrv.h>
+#define FT_TRUETYPE_DRIVER_H  <freetype/ftttdrv.h>
 
 
   /*************************************************************************
@@ -364,7 +364,7 @@
    *   types and API specific to the Type~1 format.
    *
    */
-#define FT_TYPE1_TABLES_H  <t1tables.h>
+#define FT_TYPE1_TABLES_H  <freetype/t1tables.h>
 
 
   /*************************************************************************
@@ -379,7 +379,7 @@
    *   definitions, taken from the TrueType and OpenType specifications.
    *
    */
-#define FT_TRUETYPE_IDS_H  <ttnameid.h>
+#define FT_TRUETYPE_IDS_H  <freetype/ttnameid.h>
 
 
   /*************************************************************************
@@ -392,7 +392,7 @@
    *   types and API specific to the TrueType (as well as OpenType) format.
    *
    */
-#define FT_TRUETYPE_TABLES_H  <tttables.h>
+#define FT_TRUETYPE_TABLES_H  <freetype/tttables.h>
 
 
   /*************************************************************************
@@ -406,7 +406,7 @@
    *   SFNT-based font formats (i.e., TrueType and OpenType).
    *
    */
-#define FT_TRUETYPE_TAGS_H  <tttags.h>
+#define FT_TRUETYPE_TAGS_H  <freetype/tttags.h>
 
 
   /*************************************************************************
@@ -420,7 +420,7 @@
    *   face.
    *
    */
-#define FT_BDF_H  <ftbdf.h>
+#define FT_BDF_H  <freetype/ftbdf.h>
 
 
   /*************************************************************************
@@ -434,7 +434,7 @@
    *   face.
    *
    */
-#define FT_CID_H  <ftcid.h>
+#define FT_CID_H  <freetype/ftcid.h>
 
 
   /*************************************************************************
@@ -447,7 +447,7 @@
    *   definitions of an API which supports gzip-compressed files.
    *
    */
-#define FT_GZIP_H  <ftgzip.h>
+#define FT_GZIP_H  <freetype/ftgzip.h>
 
 
   /*************************************************************************
@@ -460,7 +460,7 @@
    *   definitions of an API which supports LZW-compressed files.
    *
    */
-#define FT_LZW_H  <ftlzw.h>
+#define FT_LZW_H  <freetype/ftlzw.h>
 
 
   /*************************************************************************
@@ -473,7 +473,7 @@
    *   definitions of an API which supports bzip2-compressed files.
    *
    */
-#define FT_BZIP2_H  <ftbzip2.h>
+#define FT_BZIP2_H  <freetype/ftbzip2.h>
 
 
   /*************************************************************************
@@ -486,7 +486,7 @@
    *   definitions of an API which supports Windows FNT files.
    *
    */
-#define FT_WINFONTS_H   <ftwinfnt.h>
+#define FT_WINFONTS_H   <freetype/ftwinfnt.h>
 
 
   /*************************************************************************
@@ -499,7 +499,7 @@
    *   API of the optional glyph management component.
    *
    */
-#define FT_GLYPH_H  <ftglyph.h>
+#define FT_GLYPH_H  <freetype/ftglyph.h>
 
 
   /*************************************************************************
@@ -512,7 +512,7 @@
    *   API of the optional bitmap conversion component.
    *
    */
-#define FT_BITMAP_H  <ftbitmap.h>
+#define FT_BITMAP_H  <freetype/ftbitmap.h>
 
 
   /*************************************************************************
@@ -525,7 +525,7 @@
    *   API of the optional exact bounding box computation routines.
    *
    */
-#define FT_BBOX_H  <ftbbox.h>
+#define FT_BBOX_H  <freetype/ftbbox.h>
 
 
   /*************************************************************************
@@ -538,7 +538,7 @@
    *   API of the optional FreeType~2 cache sub-system.
    *
    */
-#define FT_CACHE_H  <ftcache.h>
+#define FT_CACHE_H  <freetype/ftcache.h>
 
 
   /*************************************************************************
@@ -612,7 +612,7 @@
    *   compiled on the Mac (note that the base API still works though).
    *
    */
-#define FT_MAC_H  <ftmac.h>
+#define FT_MAC_H  <freetype/ftmac.h>
 
 
   /*************************************************************************
@@ -625,7 +625,7 @@
    *   optional multiple-masters management API of FreeType~2.
    *
    */
-#define FT_MULTIPLE_MASTERS_H  <ftmm.h>
+#define FT_MULTIPLE_MASTERS_H  <freetype/ftmm.h>
 
 
   /*************************************************************************
@@ -639,7 +639,7 @@
    *   SFNT-based font formats (i.e., TrueType and OpenType).
    *
    */
-#define FT_SFNT_NAMES_H  <ftsnames.h>
+#define FT_SFNT_NAMES_H  <freetype/ftsnames.h>
 
 
   /*************************************************************************
@@ -653,7 +653,7 @@
    *   GPOS, GSUB, JSTF).
    *
    */
-#define FT_OPENTYPE_VALIDATE_H  <ftotval.h>
+#define FT_OPENTYPE_VALIDATE_H  <freetype/ftotval.h>
 
 
   /*************************************************************************
@@ -667,7 +667,7 @@
    *   mort, morx, bsln, just, kern, opbd, trak, prop).
    *
    */
-#define FT_GX_VALIDATE_H  <ftgxval.h>
+#define FT_GX_VALIDATE_H  <freetype/ftgxval.h>
 
 
   /*************************************************************************
@@ -680,7 +680,7 @@
    *   FreeType~2 API which accesses PFR-specific data.
    *
    */
-#define FT_PFR_H  <ftpfr.h>
+#define FT_PFR_H  <freetype/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  <ftstroke.h>
+#define FT_STROKER_H  <freetype/ftstroke.h>
 
 
   /*************************************************************************
@@ -704,20 +704,22 @@
    *   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  <ftsynth.h>
+#define FT_SYNTHESIS_H  <freetype/ftsynth.h>
 
 
   /*************************************************************************
    *
    * @macro:
-   *   FT_XFREE86_H
+   *   FT_FONT_FORMATS_H
    *
    * @description:
    *   A macro used in #include statements to name the file containing the
-   *   FreeType~2 API which provides functions specific to the XFree86 and
-   *   X.Org X11 servers.
+   *   FreeType~2 API which provides functions specific to font formats.
    */
-#define FT_XFREE86_H  <ftxf86.h>
+#define FT_FONT_FORMATS_H  <freetype/ftfntfmt.h>
+
+  /* deprecated */
+#define FT_XFREE86_H  FT_FONT_FORMATS_H
 
 
   /*************************************************************************
@@ -730,7 +732,7 @@
    *   FreeType~2 API which performs trigonometric computations (e.g.,
    *   cosines and arc tangents).
    */
-#define FT_TRIGONOMETRY_H  <fttrigon.h>
+#define FT_TRIGONOMETRY_H  <freetype/fttrigon.h>
 
 
   /*************************************************************************
@@ -742,7 +744,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  <ftlcdfil.h>
+#define FT_LCD_FILTER_H  <freetype/ftlcdfil.h>
 
 
   /*************************************************************************
@@ -751,10 +753,9 @@
    *   FT_UNPATENTED_HINTING_H
    *
    * @description:
-   *   A macro used in #include statements to name the file containing the
-   *   FreeType~2 API which performs color filtering for subpixel rendering.
+   *   Deprecated.
    */
-#define FT_UNPATENTED_HINTING_H  <ttunpat.h>
+#define FT_UNPATENTED_HINTING_H  <freetype/ttunpat.h>
 
 
   /*************************************************************************
@@ -764,9 +765,9 @@
    *
    * @description:
    *   A macro used in #include statements to name the file containing the
-   *   FreeType~2 API which performs color filtering for subpixel rendering.
+   *   FreeType~2 API which performs incremental glyph loading.
    */
-#define FT_INCREMENTAL_H  <ftincrem.h>
+#define FT_INCREMENTAL_H  <freetype/ftincrem.h>
 
 
   /*************************************************************************
@@ -778,7 +779,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  <ftgasp.h>
+#define FT_GASP_H  <freetype/ftgasp.h>
 
 
   /*************************************************************************
@@ -790,30 +791,30 @@
    *   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  <ftadvanc.h>
+#define FT_ADVANCES_H  <freetype/ftadvanc.h>
 
 
   /* */
 
-#define FT_ERROR_DEFINITIONS_H  <fterrdef.h>
+#define FT_ERROR_DEFINITIONS_H  <freetype/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           <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_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_INCREMENTAL_H          <ftincrem.h>
+#define FT_INCREMENTAL_H          <freetype/ftincrem.h>
 
-#define FT_TRUETYPE_UNPATENTED_H  <ttunpat.h>
+#define FT_TRUETYPE_UNPATENTED_H  <freetype/ttunpat.h>
 
 
   /*
@@ -821,12 +822,12 @@
    * only when building the library.
    */
 #ifdef FT2_BUILD_LIBRARY
-#define  FT_INTERNAL_INTERNAL_H  <internal/internal.h>
+#define  FT_INTERNAL_INTERNAL_H  <freetype/internal/internal.h>
 #include FT_INTERNAL_INTERNAL_H
 #endif /* FT2_BUILD_LIBRARY */
 
 
-#endif /* __FT2_BUILD_H__ */
+#endif /* FTHEADER_H_ */
 
 
 /* END */
diff --git a/include/config/ftmodule.h b/include/freetype/config/ftmodule.h
similarity index 67%
rename from include/config/ftmodule.h
rename to include/freetype/config/ftmodule.h
index 8a91d17..e145790 100644
--- a/include/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -21,16 +21,4 @@
 FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class )
 
-/*
- * New modules in 2.4.7:
-FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
-FT_USE_MODULE( FT_Module_Class, psaux_module_class )
-FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
- */
-
 /* EOF */
diff --git a/include/config/ftoption.h b/include/freetype/config/ftoption.h
similarity index 82%
rename from include/config/ftoption.h
rename to include/freetype/config/ftoption.h
index db795d3..94ccf7f 100644
--- a/include/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    User-selectable configuration macros (specification only).           */
 /*                                                                         */
-/*  Copyright 1996-2013 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTOPTION_H__
-#define __FTOPTION_H__
+#ifndef FTOPTION_H_
+#define FTOPTION_H_
 
 
 #include <ft2build.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/config/ftoption.h', where `$BUILD' is the     */
-  /*    name of a directory that is included _before_ the FreeType include */
-  /*    path during compilation.                                           */
+  /*    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.                                   */
   /*                                                                       */
   /*    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 <config/ftheader.h>                                     */
+  /*      #include <freetype/config/ftheader.h>                            */
   /*                                                                       */
   /*    will use `$BUILD/myftoptions.h' instead of this file for macro     */
   /*    definitions.                                                       */
@@ -59,9 +59,9 @@
   /*    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 <config/ftmodule.h>.                         */
+  /*    default, this file is <freetype/config/ftmodule.h>.                */
   /*                                                                       */
-  /*  We highly recommend using the third method whenever possible.        */
+  /* We highly recommend using the third method whenever possible.         */
   /*                                                                       */
   /*************************************************************************/
 
@@ -77,6 +77,36 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* If you enable this configuration option, FreeType recognizes an       */
+  /* environment variable called `FREETYPE_PROPERTIES', which can be used  */
+  /* to control the various font drivers and modules.  The controllable    */
+  /* properties are listed in the section `Controlling FreeType Modules'   */
+  /* in the reference's table of contents; currently there are properties  */
+  /* for the auto-hinter (file `ftautoh.h'), CFF (file `ftcffdrv.h'), and  */
+  /* TrueType (file `ftttdrv.h').                                          */
+  /*                                                                       */
+  /* `FREETYPE_PROPERTIES' has the following syntax form (broken here into */
+  /* multiple lines for better readability).                               */
+  /*                                                                       */
+  /*   <optional whitespace>                                               */
+  /*   <module-name1> ':'                                                  */
+  /*   <property-name1> '=' <property-value1>                              */
+  /*   <whitespace>                                                        */
+  /*   <module-name2> ':'                                                  */
+  /*   <property-name2> '=' <property-value2>                              */
+  /*   ...                                                                 */
+  /*                                                                       */
+  /* Example:                                                              */
+  /*                                                                       */
+  /*   FREETYPE_PROPERTIES=truetype:interpreter-version=35 \               */
+  /*                       cff:no-stem-darkening=1 \                       */
+  /*                       autofitter:warping=1                            */
+  /*                                                                       */
+/* #define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES */
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* Uncomment the line below if you want to activate sub-pixel rendering  */
   /* (a.k.a. LCD rendering, or ClearType) in this build of the library.    */
   /*                                                                       */
@@ -216,7 +246,7 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /*  PNG bitmap support.                                                  */
+  /* PNG bitmap support.                                                   */
   /*                                                                       */
   /*   FreeType now handles loading color bitmap glyphs in the PNG format. */
   /*   This requires help from the external libpng library.  Uncompressed  */
@@ -230,7 +260,7 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /*  HarfBuzz support.                                                    */
+  /* HarfBuzz support.                                                     */
   /*                                                                       */
   /*   FreeType uses the HarfBuzz library to improve auto-hinting of       */
   /*   OpenType fonts.  If available, many glyphs not directly addressable */
@@ -378,10 +408,6 @@
   /* The size in bytes of the render pool used by the scan-line converter  */
   /* to do all of its work.                                                */
   /*                                                                       */
-  /* This must be greater than 4KByte if you use FreeType to rasterize     */
-  /* glyphs; otherwise, you may set it to zero to avoid unnecessary        */
-  /* allocation of the render pool.                                        */
-  /*                                                                       */
 #define FT_RENDER_POOL_SIZE  16384L
 
 
@@ -435,6 +461,8 @@
   /*     af_glyph_hints_dump_points                                        */
   /*     af_glyph_hints_dump_segments                                      */
   /*     af_glyph_hints_dump_edges                                         */
+  /*     af_glyph_hints_get_num_segments                                   */
+  /*     af_glyph_hints_get_segment_offset                                 */
   /*                                                                       */
   /*   As an argument, they use another global variable:                   */
   /*                                                                       */
@@ -494,7 +522,21 @@
   /*   code will be used.                                                  */
   /*                                                                       */
   /*   Setting this macro is needed for systems that prohibit address      */
-  /*   fixups, such as BREW.                                               */
+  /*   fixups, such as BREW.  [Note that standard compilers like gcc or    */
+  /*   clang handle PIC generation automatically; you don't have to set    */
+  /*   FT_CONFIG_OPTION_PIC, which is only necessary for very special      */
+  /*   compilers.]                                                         */
+  /*                                                                       */
+  /*   Note that FT_CONFIG_OPTION_PIC support is not available for all     */
+  /*   modules (see `modules.cfg' for a complete list).  For building with */
+  /*   FT_CONFIG_OPTION_PIC support, do the following.                     */
+  /*                                                                       */
+  /*     0. Clone the repository.                                          */
+  /*     1. Define FT_CONFIG_OPTION_PIC.                                   */
+  /*     2. Remove all subdirectories in `src' that don't have             */
+  /*        FT_CONFIG_OPTION_PIC support.                                  */
+  /*     3. Comment out the corresponding modules in `modules.cfg'.        */
+  /*     4. Compile.                                                       */
   /*                                                                       */
 /* #define FT_CONFIG_OPTION_PIC */
 
@@ -588,86 +630,53 @@
   /*************************************************************************/
   /*                                                                       */
   /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
-  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
-  /* replaces the native TrueType hinting mechanism when anything but      */
-  /* FT_RENDER_MODE_MONO is requested.                                     */
+  /* subpixel hinting support into the TrueType driver.  This modifies the */
+  /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is   */
+  /* requested.                                                            */
   /*                                                                       */
-  /* Enabling this causes the TrueType driver to ignore instructions under */
-  /* certain conditions.  This is done in accordance with the guide here,  */
-  /* with some minor differences:                                          */
+  /* In particular, it modifies the bytecode interpreter to interpret (or  */
+  /* not) instructions in a certain way so that all TrueType fonts look    */
+  /* like they do in a Windows ClearType (DirectWrite) environment.  See   */
+  /* [1] for a technical overview on what this means.  See `ttinterp.h'    */
+  /* for more details on the LEAN option.                                  */
   /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /* There are three options.                                              */
   /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
+  /* 1. This option is associated with the `Infinality' moniker.           */
+  /*    Contributed by an individual nicknamed Infinality with the goal of */
+  /*    making TrueType fonts render better than on Windows.  A high       */
+  /*    amount of configurability and flexibility, down to rules for       */
+  /*    single glyphs in fonts, but also very slow.  Its experimental and  */
+  /*    slow nature and the original developer losing interest meant that  */
+  /*    this option was never enabled in default builds.                   */
   /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* 2. The new default mode for the TrueType driver.  The Infinality code */
+  /*    base was stripped to the bare minimum and all configurability      */
+  /*    removed in the name of speed and simplicity.  The configurability  */
+  /*    was mainly aimed at legacy fonts like Arial, Times New Roman, or   */
+  /*    Courier.  Legacy fonts are fonts that modify vertical stems to     */
+  /*    achieve clean black-and-white bitmaps.  The new mode focuses on    */
+  /*    applying a minimal set of rules to all fonts indiscriminately so   */
+  /*    that modern and web fonts render well while legacy fonts render    */
+  /*    okay.                                                              */
   /*                                                                       */
-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-
-  /*************************************************************************/
+  /* 3. Compile both.                                                      */
   /*                                                                       */
-  /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version  */
-  /* of the TrueType bytecode interpreter is used that doesn't implement   */
-  /* any of the patented opcodes and algorithms.  The patents related to   */
-  /* TrueType hinting have expired worldwide since May 2010; this option   */
-  /* is now deprecated.                                                    */
+  /* By undefining these, you get rendering behavior like on Windows       */
+  /* without ClearType, i.e., Windows XP without ClearType enabled and     */
+  /* Win9x (interpreter version v35).  Or not, depending on how much       */
+  /* hinting blood and testing tears the font designer put into a given    */
+  /* font.  If you define one or both subpixel hinting options, you can    */
+  /* switch between between v35 and the ones you define.                   */
   /*                                                                       */
-  /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored*  */
-  /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words,  */
-  /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or                */
-  /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time.    */
+  /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be      */
+  /* defined.                                                              */
   /*                                                                       */
-  /* This macro is only useful for a small number of font files (mostly    */
-  /* for Asian scripts) that require bytecode interpretation to properly   */
-  /* load glyphs.  For all other fonts, this produces unpleasant results,  */
-  /* thus the unpatented interpreter is never used to load glyphs from     */
-  /* TrueType fonts unless one of the following two options is used.       */
+  /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
   /*                                                                       */
-  /*   - The unpatented interpreter is explicitly activated by the user    */
-  /*     through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag         */
-  /*     when opening the FT_Face.                                         */
-  /*                                                                       */
-  /*   - FreeType detects that the FT_Face corresponds to one of the       */
-  /*     `trick' fonts (e.g., `Mingliu') it knows about.  The font engine  */
-  /*     contains a hard-coded list of font names and other matching       */
-  /*     parameters (see function `tt_face_init' in file                   */
-  /*     `src/truetype/ttobjs.c').                                         */
-  /*                                                                       */
-  /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */
-  /*                                                                       */
-  /*   {                                                                   */
-  /*     FT_Parameter  parameter;                                          */
-  /*     FT_Open_Args  open_args;                                          */
-  /*                                                                       */
-  /*                                                                       */
-  /*     parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING;                  */
-  /*                                                                       */
-  /*     open_args.flags      = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;         */
-  /*     open_args.pathname   = my_font_pathname;                          */
-  /*     open_args.num_params = 1;                                         */
-  /*     open_args.params     = &parameter;                                */
-  /*                                                                       */
-  /*     error = FT_Open_Face( library, &open_args, index, &face );        */
-  /*     ...                                                               */
-  /*   }                                                                   */
-  /*                                                                       */
-/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType    */
-  /* bytecode interpreter with a huge switch statement, rather than a call */
-  /* table.  This results in smaller and faster code for a number of       */
-  /* architectures.                                                        */
-  /*                                                                       */
-  /* Note however that on some compiler/processor combinations, undefining */
-  /* this macro will generate faster, though larger, code.                 */
-  /*                                                                       */
-#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  1         */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  2         */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  ( 1 | 2 ) */
 
 
   /*************************************************************************/
@@ -684,7 +693,7 @@
   /* fonts will not have them.                                             */
   /*                                                                       */
   /*   http://www.microsoft.com/typography/otspec/glyf.htm                 */
-  /*   http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html                 */
+  /*   https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */
   /*                                                                       */
 #undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
 
@@ -708,6 +717,24 @@
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* Option TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES controls the maximum     */
+  /* number of bytecode instructions executed for a single run of the      */
+  /* bytecode interpreter, needed to prevent infinite loops.  You don't    */
+  /* want to change this except for very special situations (e.g., making  */
+  /* a library fuzzer spend less time to handle broken fonts).             */
+  /*                                                                       */
+  /* It is not expected that this value is ever modified by a configuring  */
+  /* script; instead, it gets surrounded with #ifndef ... #endif so that   */
+  /* the value can be set as a preprocessor option on the compiler's       */
+  /* command line.                                                         */
+  /*                                                                       */
+#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES
+#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES  1000000L
+#endif
+
+
+  /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
   /****      T Y P E 1   D R I V E R    C O N F I G U R A T I O N       ****/
@@ -773,6 +800,30 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* Using CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4} it is      */
+  /* possible to set up the default values of the four control points that */
+  /* define the stem darkening behaviour of the (new) CFF engine.  For     */
+  /* more details please read the documentation of the                     */
+  /* `darkening-parameters' property of the cff driver module (file        */
+  /* `ftcffdrv.h'), which allows the control at run-time.                  */
+  /*                                                                       */
+  /* Do *not* undefine these macros!                                       */
+  /*                                                                       */
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1   500
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1   400
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2  1000
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2   275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3  1667
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3   275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4  2333
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4     0
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* CFF_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe CFF       */
   /* engine gets compiled into FreeType.  If defined, it is possible to    */
   /* switch between the two engines using the `hinting-engine' property of */
@@ -811,36 +862,72 @@
   /* grid.  To find out the optimal scaling and shifting value, various    */
   /* parameter combinations are tried and scored.                          */
   /*                                                                       */
-  /* This experimental option is only active if the render mode is         */
-  /* FT_RENDER_MODE_LIGHT.                                                 */
+  /* This experimental option is active only if the rendering mode is      */
+  /* FT_RENDER_MODE_LIGHT; you can switch warping on and off with the      */
+  /* `warping' property of the auto-hinter (see file `ftautoh.h' for more  */
+  /* information; by default it is switched off).                          */
   /*                                                                       */
-/* #define AF_CONFIG_OPTION_USE_WARPER */
+#define AF_CONFIG_OPTION_USE_WARPER
 
   /* */
 
 
   /*
-   *  This macro is obsolete.  Support has been removed in FreeType
-   *  version 2.5.
+   * This macro is obsolete.  Support has been removed in FreeType
+   * version 2.5.
    */
 /* #define FT_CONFIG_OPTION_OLD_INTERNALS */
 
 
   /*
-   * This macro is defined if either unpatented or native TrueType
-   * hinting is requested by the definitions above.
+   * This macro is defined if native TrueType hinting is requested by the
+   * definitions above.
    */
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 #define  TT_USE_BYTECODE_INTERPRETER
-#undef   TT_CONFIG_OPTION_UNPATENTED_HINTING
-#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define  TT_USE_BYTECODE_INTERPRETER
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
+#define  TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#endif
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
+#define  TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#endif
+#endif
+
+
+  /*
+   * Check CFF darkening parameters.  The checks are the same as in function
+   * `cff_property_set' in file `cffdrivr.c'.
+   */
+#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0   || \
+                                                      \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0   || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0   || \
+                                                      \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 >        \
+      CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2     || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 >        \
+      CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3     || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 >        \
+      CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4     || \
+                                                      \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \
+    CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500
+#error "Invalid CFF darkening parameters!"
 #endif
 
 FT_END_HEADER
 
 
-#endif /* __FTOPTION_H__ */
+#endif /* FTOPTION_H_ */
 
 
 /* END */
diff --git a/include/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
similarity index 95%
rename from include/config/ftstdlib.h
rename to include/freetype/config/ftstdlib.h
index b940efc..6eefa9f 100644
--- a/include/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
 /*    ANSI-specific library and header configuration file (specification   */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 2002-2007, 2009, 2011-2012 by                                */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,14 +23,13 @@
   /* FreeType normally requires.  It also defines macros to rename the     */
   /* standard functions within the FreeType source code.                   */
   /*                                                                       */
-  /* Load a file which defines __FTSTDLIB_H__ before this one to override  */
-  /* it.                                                                   */
+  /* Load a file which defines FTSTDLIB_H_ before this one to override it. */
   /*                                                                       */
   /*************************************************************************/
 
 
-#ifndef __FTSTDLIB_H__
-#define __FTSTDLIB_H__
+#ifndef FTSTDLIB_H_
+#define FTSTDLIB_H_
 
 
 #include <stddef.h>
@@ -64,6 +63,8 @@
 #define FT_INT_MAX     INT_MAX
 #define FT_INT_MIN     INT_MIN
 #define FT_UINT_MAX    UINT_MAX
+#define FT_LONG_MIN    LONG_MIN
+#define FT_LONG_MAX    LONG_MAX
 #define FT_ULONG_MAX   ULONG_MAX
 
 
@@ -141,8 +142,8 @@
   /**********************************************************************/
 
 
-#define ft_atol   atol
-#define ft_labs   labs
+#define ft_strtol  strtol
+#define ft_getenv  getenv
 
 
   /**********************************************************************/
@@ -168,7 +169,7 @@
 #include <stdarg.h>
 
 
-#endif /* __FTSTDLIB_H__ */
+#endif /* FTSTDLIB_H_ */
 
 
 /* END */
diff --git a/include/freetype.h b/include/freetype/freetype.h
similarity index 88%
rename from include/freetype.h
rename to include/freetype/freetype.h
index d6217e9..10503fd 100644
--- a/include/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType high-level API and common types (specification only).       */
 /*                                                                         */
-/*  Copyright 1996-2014 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FREETYPE_H__
-#define __FREETYPE_H__
+#ifndef FREETYPE_H_
+#define FREETYPE_H_
 
 
 #ifndef FT_FREETYPE_H
@@ -113,7 +113,8 @@
   /*    The FreeType~2 base font interface.                                */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This section describes the public high-level API of FreeType~2.    */
+  /*    This section describes the most important public high-level API    */
+  /*    functions of FreeType~2.                                           */
   /*                                                                       */
   /* <Order>                                                               */
   /*    FT_Library                                                         */
@@ -122,6 +123,7 @@
   /*    FT_GlyphSlot                                                       */
   /*    FT_CharMap                                                         */
   /*    FT_Encoding                                                        */
+  /*    FT_ENC_TAG                                                         */
   /*                                                                       */
   /*    FT_FaceRec                                                         */
   /*                                                                       */
@@ -138,9 +140,22 @@
   /*    FT_FACE_FLAG_MULTIPLE_MASTERS                                      */
   /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
   /*    FT_FACE_FLAG_EXTERNAL_STREAM                                       */
-  /*    FT_FACE_FLAG_FAST_GLYPHS                                           */
   /*    FT_FACE_FLAG_HINTER                                                */
   /*                                                                       */
+  /*    FT_HAS_HORIZONTAL                                                  */
+  /*    FT_HAS_VERTICAL                                                    */
+  /*    FT_HAS_KERNING                                                     */
+  /*    FT_HAS_FIXED_SIZES                                                 */
+  /*    FT_HAS_GLYPH_NAMES                                                 */
+  /*    FT_HAS_MULTIPLE_MASTERS                                            */
+  /*    FT_HAS_COLOR                                                       */
+  /*                                                                       */
+  /*    FT_IS_SFNT                                                         */
+  /*    FT_IS_SCALABLE                                                     */
+  /*    FT_IS_FIXED_WIDTH                                                  */
+  /*    FT_IS_CID_KEYED                                                    */
+  /*    FT_IS_TRICKY                                                       */
+  /*                                                                       */
   /*    FT_STYLE_FLAG_BOLD                                                 */
   /*    FT_STYLE_FLAG_ITALIC                                               */
   /*                                                                       */
@@ -158,6 +173,7 @@
   /*                                                                       */
   /*    FT_New_Face                                                        */
   /*    FT_Done_Face                                                       */
+  /*    FT_Reference_Face                                                  */
   /*    FT_New_Memory_Face                                                 */
   /*    FT_Open_Face                                                       */
   /*    FT_Open_Args                                                       */
@@ -170,10 +186,13 @@
   /*    FT_Request_Size                                                    */
   /*    FT_Select_Size                                                     */
   /*    FT_Size_Request_Type                                               */
+  /*    FT_Size_RequestRec                                                 */
   /*    FT_Size_Request                                                    */
   /*    FT_Set_Transform                                                   */
   /*    FT_Load_Glyph                                                      */
   /*    FT_Get_Char_Index                                                  */
+  /*    FT_Get_First_Char                                                  */
+  /*    FT_Get_Next_Char                                                   */
   /*    FT_Get_Name_Index                                                  */
   /*    FT_Load_Char                                                       */
   /*                                                                       */
@@ -190,11 +209,11 @@
   /*    FT_LOAD_NO_SCALE                                                   */
   /*    FT_LOAD_NO_HINTING                                                 */
   /*    FT_LOAD_NO_BITMAP                                                  */
-  /*    FT_LOAD_CROP_BITMAP                                                */
+  /*    FT_LOAD_NO_AUTOHINT                                                */
+  /*    FT_LOAD_COLOR                                                      */
   /*                                                                       */
   /*    FT_LOAD_VERTICAL_LAYOUT                                            */
   /*    FT_LOAD_IGNORE_TRANSFORM                                           */
-  /*    FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH                                */
   /*    FT_LOAD_FORCE_AUTOHINT                                             */
   /*    FT_LOAD_NO_RECURSE                                                 */
   /*    FT_LOAD_PEDANTIC                                                   */
@@ -205,6 +224,8 @@
   /*    FT_LOAD_TARGET_LCD                                                 */
   /*    FT_LOAD_TARGET_LCD_V                                               */
   /*                                                                       */
+  /*    FT_LOAD_TARGET_MODE                                                */
+  /*                                                                       */
   /*    FT_Render_Glyph                                                    */
   /*    FT_Render_Mode                                                     */
   /*    FT_Get_Kerning                                                     */
@@ -218,14 +239,22 @@
   /*    FT_Set_Charmap                                                     */
   /*    FT_Get_Charmap_Index                                               */
   /*                                                                       */
-  /*    FT_FSTYPE_INSTALLABLE_EMBEDDING                                    */
-  /*    FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING                             */
-  /*    FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING                              */
-  /*    FT_FSTYPE_EDITABLE_EMBEDDING                                       */
-  /*    FT_FSTYPE_NO_SUBSETTING                                            */
-  /*    FT_FSTYPE_BITMAP_EMBEDDING_ONLY                                    */
-  /*                                                                       */
   /*    FT_Get_FSType_Flags                                                */
+  /*    FT_Get_SubGlyph_Info                                               */
+  /*                                                                       */
+  /*    FT_Face_Internal                                                   */
+  /*    FT_Size_Internal                                                   */
+  /*    FT_Slot_Internal                                                   */
+  /*                                                                       */
+  /*    FT_FACE_FLAG_XXX                                                   */
+  /*    FT_STYLE_FLAG_XXX                                                  */
+  /*    FT_OPEN_XXX                                                        */
+  /*    FT_LOAD_XXX                                                        */
+  /*    FT_LOAD_TARGET_XXX                                                 */
+  /*    FT_SUBGLYPH_FLAG_XXX                                               */
+  /*    FT_FSTYPE_XXX                                                      */
+  /*                                                                       */
+  /*    FT_HAS_FAST_GLYPHS                                                 */
   /*                                                                       */
   /*************************************************************************/
 
@@ -364,8 +393,11 @@
   /*    It also embeds a memory manager (see @FT_Memory), as well as a     */
   /*    scan-line converter object (see @FT_Raster).                       */
   /*                                                                       */
-  /*    In multi-threaded applications, make sure that the same FT_Library */
-  /*    object or any of its children doesn't get accessed in parallel.    */
+  /*    In multi-threaded applications it is easiest to use one            */
+  /*    `FT_Library' object per thread.  In case this is too cumbersome,   */
+  /*    a single `FT_Library' object across threads is possible also       */
+  /*    (since FreeType version 2.5.6), as long as a mutex lock is used    */
+  /*    around @FT_New_Face and @FT_Done_Face.                             */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Library objects are normally created by @FT_Init_FreeType, and     */
@@ -378,6 +410,13 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* <Section>                                                             */
+  /*    module_management                                                  */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
   /* <Type>                                                                */
   /*    FT_Module                                                          */
   /*                                                                       */
@@ -417,6 +456,13 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* <Section>                                                             */
+  /*    base_interface                                                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
   /* <Type>                                                                */
   /*    FT_Face                                                            */
   /*                                                                       */
@@ -433,6 +479,14 @@
   /*                                                                       */
   /*    Use @FT_Done_Face to destroy it (along with its slot and sizes).   */
   /*                                                                       */
+  /*    An `FT_Face' object can only be safely used from one thread at a   */
+  /*    time.  Similarly, creation and destruction of `FT_Face' with the   */
+  /*    same @FT_Library object can only be done from one thread at a      */
+  /*    time.  On the other hand, functions like @FT_Load_Glyph and its    */
+  /*    siblings are thread-safe and do not need the lock to be held as    */
+  /*    long as the same `FT_Face' object is not used from multiple        */
+  /*    threads at the same time.                                          */
+  /*                                                                       */
   /* <Also>                                                                */
   /*    See @FT_FaceRec for the publicly accessible fields of a given face */
   /*    object.                                                            */
@@ -587,17 +641,21 @@
   /*                                                                       */
   /*    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.kostis.net/charsets/symbol.htm'.                     */
+  /*      mathematical symbols and wingdings.  For more information, see   */
+  /*      `http://www.microsoft.com/typography/otspec/recom.htm',          */
+  /*      `http://www.kostis.net/charsets/symbol.htm', and                 */
+  /*      `http://www.kostis.net/charsets/wingding.htm'.                   */
+  /*                                                                       */
+  /*      This encoding uses character codes from the PUA (Private Unicode */
+  /*      Area) in the range U+F020-U+F0FF.                                */
   /*                                                                       */
   /*    FT_ENCODING_SJIS ::                                                */
   /*      Corresponds to Japanese SJIS encoding.  More info at             */
-  /*      at `http://en.wikipedia.org/wiki/Shift_JIS'.                     */
+  /*      `http://en.wikipedia.org/wiki/Shift_JIS'.                        */
   /*      See note on multi-byte encodings below.                          */
   /*                                                                       */
   /*    FT_ENCODING_GB2312 ::                                              */
-  /*      Corresponds to an encoding system for Simplified Chinese as used */
+  /*      Corresponds to an encoding system for Simplified Chinese as      */
   /*      used in mainland China.                                          */
   /*                                                                       */
   /*    FT_ENCODING_BIG5 ::                                                */
@@ -607,7 +665,7 @@
   /*    FT_ENCODING_WANSUNG ::                                             */
   /*      Corresponds to the Korean encoding system known as Wansung.      */
   /*      For more information see                                         */
-  /*      `http://msdn.microsoft.com/en-US/goglobal/cc305154'.             */
+  /*      `https://msdn.microsoft.com/en-US/goglobal/cc305154'.            */
   /*                                                                       */
   /*    FT_ENCODING_JOHAB ::                                               */
   /*      The Korean standard character set (KS~C 5601-1992), which        */
@@ -727,15 +785,8 @@
   } FT_Encoding;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    ft_encoding_xxx                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    These constants are deprecated; use the corresponding @FT_Encoding */
-  /*    values instead.                                                    */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding `FT_Encoding' */
+  /* values instead                                                      */
 #define ft_encoding_none            FT_ENCODING_NONE
 #define ft_encoding_unicode         FT_ENCODING_UNICODE
 #define ft_encoding_symbol          FT_ENCODING_MS_SYMBOL
@@ -824,17 +875,36 @@
   /*                           font formats can have multiple faces in     */
   /*                           a font file.                                */
   /*                                                                       */
-  /*    face_index          :: The index of the face in the font file.  It */
-  /*                           is set to~0 if there is only one face in    */
+  /*    face_index          :: This field holds two different values.      */
+  /*                           Bits 0-15 are the index of the face in the  */
+  /*                           font file (starting with value~0).  They    */
+  /*                           are set to~0 if there is only one face in   */
   /*                           the font file.                              */
   /*                                                                       */
+  /*                           Bits 16-30 are relevant to GX variation     */
+  /*                           fonts only, holding the named instance      */
+  /*                           index for the current face index (starting  */
+  /*                           with value~1; value~0 indicates font access */
+  /*                           without GX variation data).  For non-GX     */
+  /*                           fonts, bits 16-30 are ignored.  If we have  */
+  /*                           the third named instance of face~4, say,    */
+  /*                           `face_index' is set to 0x00030004.          */
+  /*                                                                       */
+  /*                           Bit 31 is always zero (this is,             */
+  /*                           `face_index' is always a positive value).   */
+  /*                                                                       */
   /*    face_flags          :: A set of bit flags that give important      */
   /*                           information about the face; see             */
   /*                           @FT_FACE_FLAG_XXX for the details.          */
   /*                                                                       */
-  /*    style_flags         :: A set of bit flags indicating the style of  */
-  /*                           the face; see @FT_STYLE_FLAG_XXX for the    */
-  /*                           details.                                    */
+  /*    style_flags         :: The lower 16~bits contain a set of bit      */
+  /*                           flags indicating the style of the face; see */
+  /*                           @FT_STYLE_FLAG_XXX for the details.  Bits   */
+  /*                           16-30 hold the number of named instances    */
+  /*                           available for the current face if we have a */
+  /*                           GX variation (sub)font.  Bit 31 is always   */
+  /*                           zero (this is, `style_flags' is always a    */
+  /*                           positive value).                            */
   /*                                                                       */
   /*    num_glyphs          :: The number of glyphs in the face.  If the   */
   /*                           face is scalable and has sbits (see         */
@@ -856,6 +926,11 @@
   /*                           Can be NULL (e.g., in fonts embedded in a   */
   /*                           PDF file).                                  */
   /*                                                                       */
+  /*                           In case the font doesn't provide a specific */
+  /*                           family name entry, FreeType tries to        */
+  /*                           synthesize one, deriving it from other name */
+  /*                           entries.                                    */
+  /*                                                                       */
   /*    style_name          :: The face's style name.  This is an ASCII    */
   /*                           string, usually in English, that describes  */
   /*                           the typeface's style (like `Italic',        */
@@ -876,6 +951,10 @@
   /*                           strikes in the face.  It is set to NULL if  */
   /*                           there is no bitmap strike.                  */
   /*                                                                       */
+  /*                           Note that FreeType tries to sanitize the    */
+  /*                           strike data since they are sometimes sloppy */
+  /*                           or incorrect, but this can easily fail.     */
+  /*                                                                       */
   /*    num_charmaps        :: The number of charmaps in the face.         */
   /*                                                                       */
   /*    charmaps            :: An array of the charmaps of the face.       */
@@ -1028,7 +1107,7 @@
   /*    FT_FACE_FLAG_SCALABLE ::                                           */
   /*      Indicates that the face contains outline glyphs.  This doesn't   */
   /*      prevent bitmap strikes, i.e., a face can have both this and      */
-  /*      and @FT_FACE_FLAG_FIXED_SIZES set.                               */
+  /*      @FT_FACE_FLAG_FIXED_SIZES set.                                   */
   /*                                                                       */
   /*    FT_FACE_FLAG_FIXED_SIZES ::                                        */
   /*      Indicates that the face contains bitmap strikes.  See also the   */
@@ -1103,7 +1182,7 @@
   /*      TrueType bytecode instructions to move and scale all of its      */
   /*      subglyphs.                                                       */
   /*                                                                       */
-  /*      It is not possible to autohint such fonts using                  */
+  /*      It is not possible to auto-hint such fonts using                 */
   /*      @FT_LOAD_FORCE_AUTOHINT; it will also ignore                     */
   /*      @FT_LOAD_NO_HINTING.  You have to set both @FT_LOAD_NO_HINTING   */
   /*      and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
@@ -1147,7 +1226,7 @@
    *
    */
 #define FT_HAS_HORIZONTAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+          ( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL )
 
 
   /*************************************************************************
@@ -1161,7 +1240,7 @@
    *
    */
 #define FT_HAS_VERTICAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+          ( (face)->face_flags & FT_FACE_FLAG_VERTICAL )
 
 
   /*************************************************************************
@@ -1175,7 +1254,7 @@
    *
    */
 #define FT_HAS_KERNING( face ) \
-          ( face->face_flags & FT_FACE_FLAG_KERNING )
+          ( (face)->face_flags & FT_FACE_FLAG_KERNING )
 
 
   /*************************************************************************
@@ -1190,7 +1269,7 @@
    *
    */
 #define FT_IS_SCALABLE( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+          ( (face)->face_flags & FT_FACE_FLAG_SCALABLE )
 
 
   /*************************************************************************
@@ -1209,7 +1288,7 @@
    *
    */
 #define FT_IS_SFNT( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SFNT )
+          ( (face)->face_flags & FT_FACE_FLAG_SFNT )
 
 
   /*************************************************************************
@@ -1224,7 +1303,7 @@
    *
    */
 #define FT_IS_FIXED_WIDTH( face ) \
-          ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+          ( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
 
 
   /*************************************************************************
@@ -1239,7 +1318,7 @@
    *
    */
 #define FT_HAS_FIXED_SIZES( face ) \
-          ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+          ( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES )
 
 
   /*************************************************************************
@@ -1265,7 +1344,7 @@
    *
    */
 #define FT_HAS_GLYPH_NAMES( face ) \
-          ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+          ( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
 
 
   /*************************************************************************
@@ -1280,7 +1359,21 @@
    *
    */
 #define FT_HAS_MULTIPLE_MASTERS( face ) \
-          ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+          ( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+
+
+  /*************************************************************************
+   *
+   * @macro:
+   *   FT_IS_NAMED_INSTANCE( face )
+   *
+   * @description:
+   *   A macro that returns true whenever a face object is a named instance
+   *   of a GX variation font.
+   *
+   */
+#define FT_IS_NAMED_INSTANCE( face ) \
+          ( (face)->face_index & 0x7FFF0000L )
 
 
   /*************************************************************************
@@ -1298,7 +1391,7 @@
    *
    */
 #define FT_IS_CID_KEYED( face ) \
-          ( face->face_flags & FT_FACE_FLAG_CID_KEYED )
+          ( (face)->face_flags & FT_FACE_FLAG_CID_KEYED )
 
 
   /*************************************************************************
@@ -1312,7 +1405,7 @@
    *
    */
 #define FT_IS_TRICKY( face ) \
-          ( face->face_flags & FT_FACE_FLAG_TRICKY )
+          ( (face)->face_flags & FT_FACE_FLAG_TRICKY )
 
 
   /*************************************************************************
@@ -1326,7 +1419,7 @@
    *
    */
 #define FT_HAS_COLOR( face ) \
-          ( face->face_flags & FT_FACE_FLAG_COLOR )
+          ( (face)->face_flags & FT_FACE_FLAG_COLOR )
 
 
   /*************************************************************************/
@@ -1335,7 +1428,7 @@
   /*    FT_STYLE_FLAG_XXX                                                  */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A list of bit-flags used to indicate the style of a given face.    */
+  /*    A list of bit flags used to indicate the style of a given face.    */
   /*    These are used in the `style_flags' field of @FT_FaceRec.          */
   /*                                                                       */
   /* <Values>                                                              */
@@ -1570,15 +1663,15 @@
   /*                         change between calls of @FT_Load_Glyph and a  */
   /*                         few other functions.                          */
   /*                                                                       */
-  /*    bitmap_left       :: This is the bitmap's left bearing expressed   */
-  /*                         in integer pixels.  Of course, this is only   */
-  /*                         valid if the format is                        */
-  /*                         @FT_GLYPH_FORMAT_BITMAP.                      */
+  /*    bitmap_left       :: The bitmap's left bearing expressed in        */
+  /*                         integer pixels.  Only valid if the format is  */
+  /*                         @FT_GLYPH_FORMAT_BITMAP, this is, if the      */
+  /*                         glyph slot contains a bitmap.                 */
   /*                                                                       */
-  /*    bitmap_top        :: This is the bitmap's top bearing expressed in */
-  /*                         integer pixels.  Remember that this is the    */
-  /*                         distance from the baseline to the top-most    */
-  /*                         glyph scanline, upwards y~coordinates being   */
+  /*    bitmap_top        :: The bitmap's top bearing expressed in integer */
+  /*                         pixels.  Remember that this is the distance   */
+  /*                         from the baseline to the top-most glyph       */
+  /*                         scanline, upwards y~coordinates being         */
   /*                         *positive*.                                   */
   /*                                                                       */
   /*    outline           :: The outline descriptor for the current glyph  */
@@ -1612,11 +1705,11 @@
   /*                         needs to know about the image format.         */
   /*                                                                       */
   /*    lsb_delta         :: The difference between hinted and unhinted    */
-  /*                         left side bearing while autohinting is        */
+  /*                         left side bearing while auto-hinting is       */
   /*                         active.  Zero otherwise.                      */
   /*                                                                       */
   /*    rsb_delta         :: The difference between hinted and unhinted    */
-  /*                         right side bearing while autohinting is       */
+  /*                         right side bearing while auto-hinting is      */
   /*                         active.  Zero otherwise.                      */
   /*                                                                       */
   /* <Note>                                                                */
@@ -1639,7 +1732,7 @@
   /*    `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP.         */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    Here a small pseudo code fragment that shows how to use            */
+  /*    Here is a small pseudo code fragment that shows how to use         */
   /*    `lsb_delta' and `rsb_delta':                                       */
   /*                                                                       */
   /*    {                                                                  */
@@ -1732,8 +1825,8 @@
   /*    use @FT_New_Library instead, followed by a call to                 */
   /*    @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module).  */
   /*                                                                       */
-  /*    For multi-threading applications each thread should have its own   */
-  /*    FT_Library object.                                                 */
+  /*    See the documentation of @FT_Library and @FT_Face for              */
+  /*    multi-threading issues.                                            */
   /*                                                                       */
   /*    If you need reference-counting (cf. @FT_Reference_Library), use    */
   /*    @FT_New_Library and @FT_Done_Library.                              */
@@ -1767,7 +1860,7 @@
   /*    FT_OPEN_XXX                                                        */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A list of bit-field constants used within the `flags' field of the */
+  /*    A list of bit field constants used within the `flags' field of the */
   /*    @FT_Open_Args structure.                                           */
   /*                                                                       */
   /* <Values>                                                              */
@@ -1782,16 +1875,6 @@
   /*                                                                       */
   /*    FT_OPEN_PARAMS   :: Use the `num_params' and `params' fields.      */
   /*                                                                       */
-  /*    ft_open_memory   :: Deprecated; use @FT_OPEN_MEMORY instead.       */
-  /*                                                                       */
-  /*    ft_open_stream   :: Deprecated; use @FT_OPEN_STREAM instead.       */
-  /*                                                                       */
-  /*    ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead.     */
-  /*                                                                       */
-  /*    ft_open_driver   :: Deprecated; use @FT_OPEN_DRIVER instead.       */
-  /*                                                                       */
-  /*    ft_open_params   :: Deprecated; use @FT_OPEN_PARAMS instead.       */
-  /*                                                                       */
   /* <Note>                                                                */
   /*    The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME'     */
   /*    flags are mutually exclusive.                                      */
@@ -1802,11 +1885,14 @@
 #define FT_OPEN_DRIVER    0x8
 #define FT_OPEN_PARAMS    0x10
 
-#define ft_open_memory    FT_OPEN_MEMORY     /* deprecated */
-#define ft_open_stream    FT_OPEN_STREAM     /* deprecated */
-#define ft_open_pathname  FT_OPEN_PATHNAME   /* deprecated */
-#define ft_open_driver    FT_OPEN_DRIVER     /* deprecated */
-#define ft_open_params    FT_OPEN_PARAMS     /* deprecated */
+
+  /* these constants are deprecated; use the corresponding `FT_OPEN_XXX' */
+  /* values instead                                                      */
+#define ft_open_memory    FT_OPEN_MEMORY
+#define ft_open_stream    FT_OPEN_STREAM
+#define ft_open_pathname  FT_OPEN_PATHNAME
+#define ft_open_driver    FT_OPEN_DRIVER
+#define ft_open_params    FT_OPEN_PARAMS
 
 
   /*************************************************************************/
@@ -1871,22 +1957,22 @@
   /*    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          */
+  /*    If the @FT_OPEN_MEMORY bit is set, assume that this is a           */
   /*    memory file of `memory_size' bytes, located at `memory_address'.   */
-  /*    The data are are not copied, and the client is responsible for     */
+  /*    The data are not copied, and the client is responsible for         */
   /*    releasing and destroying them _after_ the corresponding call to    */
   /*    @FT_Done_Face.                                                     */
   /*                                                                       */
-  /*    Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a       */
+  /*    Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a        */
   /*    custom input stream `stream' is used.                              */
   /*                                                                       */
-  /*    Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this  */
+  /*    Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this   */
   /*    is a normal file and use `pathname' to open it.                    */
   /*                                                                       */
-  /*    If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to    */
+  /*    If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to     */
   /*    open the file with the driver whose handler is in `driver'.        */
   /*                                                                       */
-  /*    If the `FT_OPEN_PARAMS' bit is set, the parameters given by        */
+  /*    If the @FT_OPEN_PARAMS bit is set, the parameters given by         */
   /*    `num_params' and `params' is used.  They are ignored otherwise.    */
   /*                                                                       */
   /*    Ideally, both the `pathname' and `params' fields should be tagged  */
@@ -1921,13 +2007,12 @@
   /* <Input>                                                               */
   /*    pathname   :: A path to the font file.                             */
   /*                                                                       */
-  /*    face_index :: The index of the face within the font.  The first    */
-  /*                  face has index~0.                                    */
+  /*    face_index :: See @FT_Open_Face for a detailed description of this */
+  /*                  parameter.                                           */
   /*                                                                       */
   /* <Output>                                                              */
   /*    aface      :: A handle to a new face object.  If `face_index' is   */
   /*                  greater than or equal to zero, it must be non-NULL.  */
-  /*                  See @FT_Open_Face for more details.                  */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -1960,13 +2045,12 @@
   /*                                                                       */
   /*    file_size  :: The size of the memory chunk used by the font data.  */
   /*                                                                       */
-  /*    face_index :: The index of the face within the font.  The first    */
-  /*                  face has index~0.                                    */
+  /*    face_index :: See @FT_Open_Face for a detailed description of this */
+  /*                  parameter.                                           */
   /*                                                                       */
   /* <Output>                                                              */
   /*    aface      :: A handle to a new face object.  If `face_index' is   */
   /*                  greater than or equal to zero, it must be non-NULL.  */
-  /*                  See @FT_Open_Face for more details.                  */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -1998,13 +2082,43 @@
   /*    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    */
-  /*                  face has index~0.                                    */
+  /*    face_index :: This field holds two different values.  Bits 0-15    */
+  /*                  are the index of the face in the font file (starting */
+  /*                  with value~0).  Set it to~0 if there is only one     */
+  /*                  face in the font file.                               */
+  /*                                                                       */
+  /*                  Bits 16-30 are relevant to GX variation fonts only,  */
+  /*                  specifying the named instance index for the current  */
+  /*                  face index (starting with value~1; value~0 makes     */
+  /*                  FreeType ignore named instances).  For non-GX fonts, */
+  /*                  bits 16-30 are ignored.  Assuming that you want to   */
+  /*                  access the third named instance in face~4,           */
+  /*                  `face_index' should be set to 0x00030004.  If you    */
+  /*                  want to access face~4 without GX variation handling, */
+  /*                  simply set `face_index' to value~4.                  */
+  /*                                                                       */
+  /*                  FT_Open_Face and its siblings can be used to quickly */
+  /*                  check whether the font format of a given font        */
+  /*                  resource is supported by FreeType.  In general, if   */
+  /*                  the `face_index' argument is negative, the           */
+  /*                  function's return value is~0 if the font format is   */
+  /*                  recognized, or non-zero otherwise.  The function     */
+  /*                  allocates a more or less empty face handle in        */
+  /*                  `*aface' (if `aface' isn't NULL); the only two       */
+  /*                  useful fields in this special case are               */
+  /*                  `face->num_faces' and `face->style_flags'.  For any  */
+  /*                  negative value of `face_index', `face->num_faces'    */
+  /*                  gives the number of faces within the font file.  For */
+  /*                  the negative value `-(N+1)' (with `N' a 16-bit       */
+  /*                  value), bits 16-30 in `face->style_flags' give the   */
+  /*                  number of named instances in face `N' if we have a   */
+  /*                  GX variation font (or zero otherwise).  After        */
+  /*                  examination, the returned @FT_Face structure should  */
+  /*                  be deallocated with a call to @FT_Done_Face.         */
   /*                                                                       */
   /* <Output>                                                              */
   /*    aface      :: A handle to a new face object.  If `face_index' is   */
   /*                  greater than or equal to zero, it must be non-NULL.  */
-  /*                  See note below.                                      */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -2014,16 +2128,6 @@
   /*    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         */
-  /*    format of a given font resource is supported by FreeType.  If the  */
-  /*    `face_index' field is negative, the function's return value is~0   */
-  /*    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' 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.                */
-  /*                                                                       */
   /*    Each new face object created with this function also owns a        */
   /*    default @FT_Size object, accessible as `face->size'.               */
   /*                                                                       */
@@ -2034,6 +2138,74 @@
   /*    See the discussion of reference counters in the description of     */
   /*    @FT_Reference_Face.                                                */
   /*                                                                       */
+  /*    To loop over all faces, use code similar to the following snippet  */
+  /*    (omitting the error handling).                                     */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      ...                                                              */
+  /*      FT_Face  face;                                                   */
+  /*      FT_Long  i, num_faces;                                           */
+  /*                                                                       */
+  /*                                                                       */
+  /*      error = FT_Open_Face( library, args, -1, &face );                */
+  /*      if ( error ) { ... }                                             */
+  /*                                                                       */
+  /*      num_faces = face->num_faces;                                     */
+  /*      FT_Done_Face( face );                                            */
+  /*                                                                       */
+  /*      for ( i = 0; i < num_faces; i++ )                                */
+  /*      {                                                                */
+  /*        ...                                                            */
+  /*        error = FT_Open_Face( library, args, i, &face );               */
+  /*        ...                                                            */
+  /*        FT_Done_Face( face );                                          */
+  /*        ...                                                            */
+  /*      }                                                                */
+  /*    }                                                                  */
+  /*                                                                       */
+  /*    To loop over all valid values for `face_index', use something      */
+  /*    similar to the following snippet, again without error handling.    */
+  /*    The code accesses all faces immediately (thus only a single call   */
+  /*    of `FT_Open_Face' within the do-loop), with and without named      */
+  /*    instances.                                                         */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      ...                                                              */
+  /*      FT_Face  face;                                                   */
+  /*                                                                       */
+  /*      FT_Long  num_faces     = 0;                                      */
+  /*      FT_Long  num_instances = 0;                                      */
+  /*                                                                       */
+  /*      FT_Long  face_idx     = 0;                                       */
+  /*      FT_Long  instance_idx = 0;                                       */
+  /*                                                                       */
+  /*                                                                       */
+  /*      do                                                               */
+  /*      {                                                                */
+  /*        FT_Long  id = ( instance_idx << 16 ) + face_idx;               */
+  /*                                                                       */
+  /*                                                                       */
+  /*        error = FT_Open_Face( library, args, id, &face );              */
+  /*        if ( error ) { ... }                                           */
+  /*                                                                       */
+  /*        num_faces     = face->num_faces;                               */
+  /*        num_instances = face->style_flags >> 16;                       */
+  /*                                                                       */
+  /*        ...                                                            */
+  /*                                                                       */
+  /*        FT_Done_Face( face );                                          */
+  /*                                                                       */
+  /*        if ( instance_idx < num_instances )                            */
+  /*          instance_idx++;                                              */
+  /*        else                                                           */
+  /*        {                                                              */
+  /*          face_idx++;                                                  */
+  /*          instance_idx = 0;                                            */
+  /*        }                                                              */
+  /*                                                                       */
+  /*      } while ( face_idx < num_faces )                                 */
+  /*    }                                                                  */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Open_Face( FT_Library           library,
                 const FT_Open_Args*  args,
@@ -2177,17 +2349,26 @@
   /*    FT_Size_Request_Type                                               */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    An enumeration type that lists the supported size request types.   */
+  /*    An enumeration type that lists the supported size request types,   */
+  /*    i.e., what input size (in font units) maps to the requested output */
+  /*    size (in pixels, as computed from the arguments of                 */
+  /*    @FT_Size_Request).                                                 */
   /*                                                                       */
   /* <Values>                                                              */
   /*    FT_SIZE_REQUEST_TYPE_NOMINAL ::                                    */
   /*      The nominal size.  The `units_per_EM' field of @FT_FaceRec is    */
   /*      used to determine both scaling values.                           */
   /*                                                                       */
+  /*      This is the standard scaling found in most applications.  In     */
+  /*      particular, use this size request type for TrueType fonts if     */
+  /*      they provide optical scaling or something similar.  Note,        */
+  /*      however, that `units_per_EM' is a rather abstract value which    */
+  /*      bears no relation to the actual size of the glyphs in a font.    */
+  /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_REAL_DIM ::                                   */
-  /*      The real dimension.  The sum of the the `ascender' and (minus    */
-  /*      of) the `descender' fields of @FT_FaceRec are used to determine  */
-  /*      both scaling values.                                             */
+  /*      The real dimension.  The sum of the `ascender' and (minus of)    */
+  /*      the `descender' fields of @FT_FaceRec are used to determine both */
+  /*      scaling values.                                                  */
   /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_BBOX ::                                       */
   /*      The font bounding box.  The width and height of the `bbox' field */
@@ -2237,22 +2418,29 @@
   /* <Fields>                                                              */
   /*    type           :: See @FT_Size_Request_Type.                       */
   /*                                                                       */
-  /*    width          :: The desired width.                               */
+  /*    width          :: The desired width, given as a 26.6 fractional    */
+  /*                      point value (with 72pt = 1in).                   */
   /*                                                                       */
-  /*    height         :: The desired height.                              */
+  /*    height         :: The desired height, given as a 26.6 fractional   */
+  /*                      point value (with 72pt = 1in).                   */
   /*                                                                       */
-  /*    horiResolution :: The horizontal resolution.  If set to zero,      */
-  /*                      `width' is treated as a 26.6 fractional pixel    */
-  /*                      value.                                           */
+  /*    horiResolution :: The horizontal resolution (dpi, i.e., pixels per */
+  /*                      inch).  If set to zero, `width' is treated as a  */
+  /*                      26.6 fractional *pixel* value.                   */
   /*                                                                       */
-  /*    vertResolution :: The vertical resolution.  If set to zero,        */
-  /*                      `height' is treated as a 26.6 fractional pixel   */
-  /*                      value.                                           */
+  /*    vertResolution :: The vertical resolution (dpi, i.e., pixels per   */
+  /*                      inch).  If set to zero, `height' is treated as a */
+  /*                      26.6 fractional *pixel* value.                   */
   /*                                                                       */
   /* <Note>                                                                */
   /*    If `width' is zero, then the horizontal scaling value is set equal */
   /*    to the vertical scaling value, and vice versa.                     */
   /*                                                                       */
+  /*    If `type' is FT_SIZE_REQUEST_TYPE_SCALES, `width' and `height' are */
+  /*    interpreted directly as 16.16 fractional scaling values, without   */
+  /*    any further modification, and both `horiResolution' and            */
+  /*    `vertResolution' are ignored.                                      */
+  /*                                                                       */
   typedef struct  FT_Size_RequestRec_
   {
     FT_Size_Request_Type  type;
@@ -2424,6 +2612,10 @@
   /*    don't have a corresponding glyph in the font).  See the discussion */
   /*    of the @FT_FACE_FLAG_CID_KEYED flag for more details.              */
   /*                                                                       */
+  /*    If you receive `FT_Err_Glyph_Too_Big', try getting the glyph       */
+  /*    outline at EM size, then scale it manually and fill it as a        */
+  /*    graphics operation.                                                */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Load_Glyph( FT_Face   face,
                  FT_UInt   glyph_index,
@@ -2471,7 +2663,7 @@
    *   FT_LOAD_XXX
    *
    * @description:
-   *   A list of bit-field constants used with @FT_Load_Glyph to indicate
+   *   A list of bit field constants used with @FT_Load_Glyph to indicate
    *   what kind of operations to perform during glyph loading.
    *
    * @values:
@@ -2540,11 +2732,6 @@
    *     Indicates that the auto-hinter is preferred over the font's native
    *     hinter.  See also the note below.
    *
-   *   FT_LOAD_CROP_BITMAP ::
-   *     Indicates that the font driver should crop the loaded bitmap glyph
-   *     (i.e., remove all space around its black bits).  Not all drivers
-   *     implement this.
-   *
    *   FT_LOAD_PEDANTIC ::
    *     Indicates that the font driver should perform pedantic verifications
    *     during glyph loading.  This is mostly used to detect broken glyphs
@@ -2555,9 +2742,6 @@
    *     result in partially hinted or distorted glyphs in case a glyph's
    *     bytecode is buggy.
    *
-   *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
-   *     Ignored.  Deprecated.
-   *
    *   FT_LOAD_NO_RECURSE ::
    *     Indicate that the font driver should not load composite glyphs
    *     recursively.  Instead, it should set the `num_subglyph' and
@@ -2596,6 +2780,22 @@
    *     bitmaps transparently.  Those bitmaps will be in the
    *     @FT_PIXEL_MODE_GRAY format.
    *
+   *   FT_LOAD_COMPUTE_METRICS ::
+   *     This flag sets computing glyph metrics without the use of bundled
+   *     metrics tables (for example, the `hdmx' table in TrueType fonts).
+   *     Well-behaving fonts have optimized bundled metrics and these should
+   *     be used.  This flag is mainly used by font validating or font
+   *     editing applications, which need to ignore, verify, or edit those
+   *     tables.
+   *
+   *     Currently, this flag is only implemented for TrueType fonts.
+   *
+   *   FT_LOAD_CROP_BITMAP ::
+   *     Ignored.  Deprecated.
+   *
+   *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+   *     Ignored.  Deprecated.
+   *
    * @note:
    *   By default, hinting is enabled and the font's native hinter (see
    *   @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter.  You can
@@ -2635,6 +2835,7 @@
 #define FT_LOAD_NO_AUTOHINT                  ( 1L << 15 )
   /* Bits 16..19 are used by `FT_LOAD_TARGET_' */
 #define FT_LOAD_COLOR                        ( 1L << 20 )
+#define FT_LOAD_COMPUTE_METRICS              ( 1L << 21 )
 
   /* */
 
@@ -2657,9 +2858,6 @@
    *   have specified (e.g., the TrueType bytecode interpreter).  You can set
    *   @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
    *
-   *   Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it
-   *   always implies @FT_LOAD_FORCE_AUTOHINT.
-   *
    * @values:
    *   FT_LOAD_TARGET_NORMAL ::
    *     This corresponds to the default hinting algorithm, optimized for
@@ -2667,11 +2865,14 @@
    *     @FT_LOAD_TARGET_MONO instead.
    *
    *   FT_LOAD_TARGET_LIGHT ::
-   *     A lighter hinting algorithm for non-monochrome modes.  Many
-   *     generated glyphs are more fuzzy but better resemble its original
-   *     shape.  A bit like rendering on Mac OS~X.
-   *
-   *     As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT.
+   *     A lighter hinting algorithm for gray-level modes.  Many generated
+   *     glyphs are fuzzier but better resemble their original shape.  This
+   *     is achieved by snapping glyphs to the pixel grid only vertically
+   *     (Y-axis), as is done by Microsoft's ClearType and Adobe's
+   *     proprietary font renderer.  This preserves inter-glyph spacing in
+   *     horizontal text.  The snapping is done either by the native font
+   *     driver if the driver itself and the font support it or by the
+   *     auto-hinter.
    *
    *   FT_LOAD_TARGET_MONO ::
    *     Strong hinting algorithm that should only be used for monochrome
@@ -2692,7 +2893,7 @@
    *
    *   If @FT_LOAD_RENDER is also set, the glyph is rendered in the
    *   corresponding mode (i.e., the mode that matches the used algorithm
-   *   best).  An exeption is FT_LOAD_TARGET_MONO since it implies
+   *   best).  An exception is FT_LOAD_TARGET_MONO since it implies
    *   @FT_LOAD_MONOCHROME.
    *
    *   You can use a hinting algorithm that doesn't correspond to the same
@@ -2778,7 +2979,10 @@
   /*    field in the @FT_GlyphSlotRec structure gives the format of the    */
   /*    returned bitmap.                                                   */
   /*                                                                       */
-  /*    All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity.   */
+  /*    All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity,   */
+  /*    indicating pixel coverage.  Use linear alpha blending and gamma    */
+  /*    correction to correctly render non-monochrome glyph bitmaps onto a */
+  /*    surface; see @FT_Render_Glyph.                                     */
   /*                                                                       */
   /* <Values>                                                              */
   /*    FT_RENDER_MODE_NORMAL ::                                           */
@@ -2832,19 +3036,8 @@
   } FT_Render_Mode;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    ft_render_mode_xxx                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    These constants are deprecated.  Use the corresponding             */
-  /*    @FT_Render_Mode values instead.                                    */
-  /*                                                                       */
-  /* <Values>                                                              */
-  /*    ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL                */
-  /*    ft_render_mode_mono   :: see @FT_RENDER_MODE_MONO                  */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_Render_Mode' values instead                       */
 #define ft_render_mode_normal  FT_RENDER_MODE_NORMAL
 #define ft_render_mode_mono    FT_RENDER_MODE_MONO
 
@@ -2875,6 +3068,83 @@
   /*    To get meaningful results, font scaling values must be set with    */
   /*    functions like @FT_Set_Char_Size before calling FT_Render_Glyph.   */
   /*                                                                       */
+  /*    When FreeType outputs a bitmap of a glyph, it really outputs an    */
+  /*    alpha coverage map.  If a pixel is completely covered by a         */
+  /*    filled-in outline, the bitmap contains 0xFF at that pixel, meaning */
+  /*    that 0xFF/0xFF fraction of that pixel is covered, meaning the      */
+  /*    pixel is 100% black (or 0% bright).  If a pixel is only 50%        */
+  /*    covered (value 0x80), the pixel is made 50% black (50% bright or a */
+  /*    middle shade of grey).  0% covered means 0% black (100% bright or  */
+  /*    white).                                                            */
+  /*                                                                       */
+  /*    On high-DPI screens like on smartphones and tablets, the pixels    */
+  /*    are so small that their chance of being completely covered and     */
+  /*    therefore completely black are fairly good.  On the low-DPI        */
+  /*    screens, however, the situation is different.  The pixels are too  */
+  /*    large for most of the details of a glyph and shades of gray are    */
+  /*    the norm rather than the exception.                                */
+  /*                                                                       */
+  /*    This is relevant because all our screens have a second problem:    */
+  /*    they are not linear.  1~+~1 is not~2.  Twice the value does not    */
+  /*    result in twice the brightness.  When a pixel is only 50% covered, */
+  /*    the coverage map says 50% black, and this translates to a pixel    */
+  /*    value of 128 when you use 8~bits per channel (0-255).  However,    */
+  /*    this does not translate to 50% brightness for that pixel on our    */
+  /*    sRGB and gamma~2.2 screens.  Due to their non-linearity, they      */
+  /*    dwell longer in the darks and only a pixel value of about 186      */
+  /*    results in 50% brightness – 128 ends up too dark on both bright    */
+  /*    and dark backgrounds.  The net result is that dark text looks      */
+  /*    burnt-out, pixely and blotchy on bright background, bright text    */
+  /*    too frail on dark backgrounds, and colored text on colored         */
+  /*    background (for example, red on green) seems to have dark halos or */
+  /*    `dirt' around it.  The situation is especially ugly for diagonal   */
+  /*    stems like in `w' glyph shapes where the quality of FreeType's     */
+  /*    anti-aliasing depends on the correct display of grays.  On         */
+  /*    high-DPI screens where smaller, fully black pixels reign supreme,  */
+  /*    this doesn't matter, but on our low-DPI screens with all the gray  */
+  /*    shades, it does.  0% and 100% brightness are the same things in    */
+  /*    linear and non-linear space, just all the shades in-between        */
+  /*    aren't.                                                            */
+  /*                                                                       */
+  /*    The blending function for placing text over a background is        */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      dst = alpha * src + (1 - alpha) * dst    ,                       */
+  /*    }                                                                  */
+  /*                                                                       */
+  /*    which is known as the OVER operator.                               */
+  /*                                                                       */
+  /*    To correctly composite an antialiased pixel of a glyph onto a      */
+  /*    surface,                                                           */
+  /*                                                                       */
+  /*    1. take the foreground and background colors (e.g., in sRGB space) */
+  /*       and apply gamma to get them in a linear space,                  */
+  /*                                                                       */
+  /*    2. use OVER to blend the two linear colors using the glyph pixel   */
+  /*       as the alpha value (remember, the glyph bitmap is an alpha      */
+  /*       coverage bitmap), and                                           */
+  /*                                                                       */
+  /*    3. apply inverse gamma to the blended pixel and write it back to   */
+  /*       the image.                                                      */
+  /*                                                                       */
+  /*    Internal testing at Adobe found that a target inverse gamma of~1.8 */
+  /*    for step~3 gives good results across a wide range of displays with */
+  /*    an sRGB gamma curve or a similar one.                              */
+  /*                                                                       */
+  /*    This process can cost performance.  There is an approximation that */
+  /*    does not need to know about the background color; see              */
+  /*    https://bel.fi/alankila/lcd/ and                                   */
+  /*    https://bel.fi/alankila/lcd/alpcor.html for details.               */
+  /*                                                                       */
+  /*    *ATTENTION*: Linear blending is even more important when dealing   */
+  /*    with subpixel-rendered glyphs to prevent color-fringing!  A        */
+  /*    subpixel-rendered glyph must first be filtered with a filter that  */
+  /*    gives equal weight to the three color primaries and does not       */
+  /*    exceed a sum of 0x100, see section @lcd_filtering.  Then the       */
+  /*    only difference to gray linear blending is that subpixel-rendered  */
+  /*    linear blending is done 3~times per pixel: red foreground subpixel */
+  /*    to red background subpixel and so on for green and blue.           */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Render_Glyph( FT_GlyphSlot    slot,
                    FT_Render_Mode  render_mode );
@@ -2890,15 +3160,22 @@
   /*    @FT_Get_Kerning.                                                   */
   /*                                                                       */
   /* <Values>                                                              */
-  /*    FT_KERNING_DEFAULT  :: Return scaled and grid-fitted kerning       */
-  /*                           distances (value is~0).                     */
+  /*    FT_KERNING_DEFAULT  :: Return grid-fitted kerning distances in     */
+  /*                           pixels (value is~0).  Whether they are      */
+  /*                           scaled depends on @FT_LOAD_NO_SCALE.        */
   /*                                                                       */
-  /*    FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning    */
-  /*                           distances.                                  */
+  /*    FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in  */
+  /*                           26.6 fractional pixels.  Whether they are   */
+  /*                           scaled depends on @FT_LOAD_NO_SCALE.        */
   /*                                                                       */
   /*    FT_KERNING_UNSCALED :: Return the kerning vector in original font  */
   /*                           units.                                      */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    FT_KERNING_DEFAULT returns full pixel values; it also makes        */
+  /*    FreeType heuristically scale down kerning distances at small ppem  */
+  /*    values so that they don't become too big.                          */
+  /*                                                                       */
   typedef enum  FT_Kerning_Mode_
   {
     FT_KERNING_DEFAULT  = 0,
@@ -2908,39 +3185,10 @@
   } FT_Kerning_Mode;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Const>                                                               */
-  /*    ft_kerning_default                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    This constant is deprecated.  Please use @FT_KERNING_DEFAULT       */
-  /*    instead.                                                           */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_Kerning_Mode' values instead                      */
 #define ft_kerning_default   FT_KERNING_DEFAULT
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Const>                                                               */
-  /*    ft_kerning_unfitted                                                */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    This constant is deprecated.  Please use @FT_KERNING_UNFITTED      */
-  /*    instead.                                                           */
-  /*                                                                       */
 #define ft_kerning_unfitted  FT_KERNING_UNFITTED
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Const>                                                               */
-  /*    ft_kerning_unscaled                                                */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    This constant is deprecated.  Please use @FT_KERNING_UNSCALED      */
-  /*    instead.                                                           */
-  /*                                                                       */
 #define ft_kerning_unscaled  FT_KERNING_UNSCALED
 
 
@@ -2964,9 +3212,10 @@
   /*                   kerning vector.                                     */
   /*                                                                       */
   /* <Output>                                                              */
-  /*    akerning    :: The kerning vector.  This is either in font units   */
-  /*                   or in pixels (26.6 format) for scalable formats,    */
-  /*                   and in pixels for fixed-sizes formats.              */
+  /*    akerning    :: The kerning vector.  This is either in font units,  */
+  /*                   fractional pixels (26.6 format), or pixels for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -3062,7 +3311,7 @@
   /*    `.notdef').                                                        */
   /*                                                                       */
   /*    This function always returns an error if the config macro          */
-  /*    `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */
+  /*    `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoption.h'.  */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Get_Glyph_Name( FT_Face     face,
@@ -3251,6 +3500,13 @@
   /*      }                                                                */
   /*    }                                                                  */
   /*                                                                       */
+  /*    Be aware that character codes can have values up to 0xFFFFFFFF;    */
+  /*    this might happen for non-Unicode or malformed cmaps.  However,    */
+  /*    even with regular Unicode encoding, so-called `last resort fonts'  */
+  /*    (using SFNT cmap format 13, see function @FT_Get_CMap_Format)      */
+  /*    normally have entries for all Unicode characters up to 0x1FFFFF,   */
+  /*    which can cause *a lot* of iterations.                             */
+  /*                                                                       */
   /*    Note that `*agindex' is set to~0 if the charmap is empty.  The     */
   /*    result itself can be~0 in two cases: if the charmap is empty or    */
   /*    if the value~0 is the first valid character code.                  */
@@ -3410,8 +3666,9 @@
   /*    @FT_Get_FSType_Flags; they inform client applications of embedding */
   /*    and subsetting restrictions associated with a font.                */
   /*                                                                       */
-  /*    See http://www.adobe.com/devnet/acrobat/pdfs/FontPolicies.pdf for  */
-  /*    more details.                                                      */
+  /*    See                                                                */
+  /*    http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */
+  /*    for more details.                                                  */
   /*                                                                       */
   /* <Values>                                                              */
   /*    FT_FSTYPE_INSTALLABLE_EMBEDDING ::                                 */
@@ -3445,6 +3702,9 @@
   /*      bitmaps available in the font, then the font is unembeddable.    */
   /*                                                                       */
   /* <Note>                                                                */
+  /*    The flags are ORed together, thus more than a single value can be  */
+  /*    returned.                                                          */
+  /*                                                                       */
   /*    While the fsType flags can indicate that a font may be embedded, a */
   /*    license with the font vendor may be separately required to use the */
   /*    font in this way.                                                  */
@@ -3510,8 +3770,8 @@
   /*                                                                       */
   /*      http://www.unicode.org/reports/tr37/                             */
   /*                                                                       */
-  /*    To date (November 2012), the character with the most variants is   */
-  /*    U+9089, having 31 such IVS.                                        */
+  /*    To date (November 2014), the character with the most variants is   */
+  /*    U+9089, having 32 such IVS.                                        */
   /*                                                                       */
   /*    Adobe and MS decided to support IVS with a new cmap subtable       */
   /*    (format~14).  It is an odd subtable because it is not a mapping of */
@@ -3762,12 +4022,6 @@
              FT_Long  c );
 
 
-  /* */
-
-  /* The following #if 0 ... #endif is for the documentation formatter, */
-  /* hiding the internal `FT_MULFIX_INLINED' macro.                     */
-
-#if 0
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -3801,17 +4055,6 @@
   FT_MulFix( FT_Long  a,
              FT_Long  b );
 
-  /* */
-#endif
-
-#ifdef FT_MULFIX_INLINED
-#define FT_MulFix( a, b )  FT_MULFIX_INLINED( a, b )
-#else
-  FT_EXPORT( FT_Long )
-  FT_MulFix( FT_Long  a,
-             FT_Long  b );
-#endif
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -3824,18 +4067,12 @@
   /*    used to divide a given value by a 16.16 fixed-point factor.        */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    a :: The first multiplier.                                         */
-  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
-  /*         possible (see note below).                                    */
+  /*    a :: The numerator.                                                */
+  /*    b :: The denominator.  Use a 16.16 factor here.                    */
   /*                                                                       */
   /* <Return>                                                              */
   /*    The result of `(a*0x10000)/b'.                                     */
   /*                                                                       */
-  /* <Note>                                                                */
-  /*    The optimization for FT_DivFix() is simple: If (a~<<~16) fits in   */
-  /*    32~bits, then the division is computed directly.  Otherwise, we    */
-  /*    use a specialized version of @FT_MulDiv.                           */
-  /*                                                                       */
   FT_EXPORT( FT_Long )
   FT_DivFix( FT_Long  a,
              FT_Long  b );
@@ -3853,7 +4090,8 @@
   /*    a :: The number to be rounded.                                     */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    The result of `(a + 0x8000) & -0x10000'.                           */
+  /*    `a' rounded to nearest 16.16 fixed integer, halfway cases away     */
+  /*    from zero.                                                         */
   /*                                                                       */
   FT_EXPORT( FT_Fixed )
   FT_RoundFix( FT_Fixed  a );
@@ -3872,7 +4110,7 @@
   /*    a :: The number for which the ceiling function is to be computed.  */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    The result of `(a + 0x10000 - 1) & -0x10000'.                      */
+  /*    `a' rounded towards plus infinity.                                 */
   /*                                                                       */
   FT_EXPORT( FT_Fixed )
   FT_CeilFix( FT_Fixed  a );
@@ -3891,7 +4129,7 @@
   /*    a :: The number for which the floor function is to be computed.    */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    The result of `a & -0x10000'.                                      */
+  /*    `a' rounded towards minus infinity.                                */
   /*                                                                       */
   FT_EXPORT( FT_Fixed )
   FT_FloorFix( FT_Fixed  a );
@@ -3935,6 +4173,18 @@
   /*    even a new release of FreeType with only documentation changes     */
   /*    increases the version number.                                      */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Library_Version                                                 */
+  /*                                                                       */
+  /*    FREETYPE_MAJOR                                                     */
+  /*    FREETYPE_MINOR                                                     */
+  /*    FREETYPE_PATCH                                                     */
+  /*                                                                       */
+  /*    FT_Face_CheckTrueTypePatents                                       */
+  /*    FT_Face_SetUnpatentedHinting                                       */
+  /*                                                                       */
+  /*    FREETYPE_XXX                                                       */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -3959,8 +4209,8 @@
    *
    */
 #define FREETYPE_MAJOR  2
-#define FREETYPE_MINOR  5
-#define FREETYPE_PATCH  3
+#define FREETYPE_MINOR  7
+#define FREETYPE_PATCH  0
 
 
   /*************************************************************************/
@@ -4005,20 +4255,13 @@
   /*    FT_Face_CheckTrueTypePatents                                       */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Parse all bytecode instructions of a TrueType font file to check   */
-  /*    whether any of the patented opcodes are used.  This is only useful */
-  /*    if you want to be able to use the unpatented hinter with           */
-  /*    fonts that do *not* use these opcodes.                             */
-  /*                                                                       */
-  /*    Note that this function parses *all* glyph instructions in the     */
-  /*    font file, which may be slow.                                      */
+  /*    Deprecated, does nothing.                                          */
   /*                                                                       */
   /* <Input>                                                               */
   /*    face :: A face handle.                                             */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    1~if this is a TrueType font that uses one of the patented         */
-  /*    opcodes, 0~otherwise.                                              */
+  /*    Always returns false.                                              */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Since May 2010, TrueType hinting is no longer patented.            */
@@ -4036,9 +4279,7 @@
   /*    FT_Face_SetUnpatentedHinting                                       */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Enable or disable the unpatented hinter for a given face.          */
-  /*    Only enable it if you have determined that the face doesn't        */
-  /*    use any patented opcodes (see @FT_Face_CheckTrueTypePatents).      */
+  /*    Deprecated, does nothing.                                          */
   /*                                                                       */
   /* <Input>                                                               */
   /*    face  :: A face handle.                                            */
@@ -4046,9 +4287,7 @@
   /*    value :: New boolean setting.                                      */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    The old setting value.  This will always be false if this is not   */
-  /*    an SFNT font, or if the unpatented hinter is not compiled in this  */
-  /*    instance of the library.                                           */
+  /*    Always returns false.                                              */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Since May 2010, TrueType hinting is no longer patented.            */
@@ -4065,7 +4304,7 @@
 
 FT_END_HEADER
 
-#endif /* __FREETYPE_H__ */
+#endif /* FREETYPE_H_ */
 
 
 /* END */
diff --git a/include/ftadvanc.h b/include/freetype/ftadvanc.h
similarity index 97%
rename from include/ftadvanc.h
rename to include/freetype/ftadvanc.h
index 8f7e2fc..023dd84 100644
--- a/include/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (specification only).            */
 /*                                                                         */
-/*  Copyright 2008, 2013 by                                                */
+/*  Copyright 2008-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTADVANC_H__
-#define __FTADVANC_H__
+#ifndef FTADVANC_H_
+#define FTADVANC_H_
 
 
 #include <ft2build.h>
@@ -48,6 +48,11 @@
    * @description:
    *   This section contains functions to quickly extract advance values
    *   without handling glyph outlines, if possible.
+   *
+   * @order:
+   *   FT_Get_Advance
+   *   FT_Get_Advances
+   *
    */
 
 
@@ -72,7 +77,7 @@
   /*    and hinting of the glyph outline, are extremely slow by            */
   /*    comparison.                                                        */
   /*                                                                       */
-#define FT_ADVANCE_FLAG_FAST_ONLY  0x20000000UL
+#define FT_ADVANCE_FLAG_FAST_ONLY  0x20000000L
 
 
   /*************************************************************************/
@@ -171,12 +176,12 @@
                    FT_Int32   load_flags,
                    FT_Fixed  *padvances );
 
-/* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTADVANC_H__ */
+#endif /* FTADVANC_H_ */
 
 
 /* END */
diff --git a/include/ftautoh.h b/include/freetype/ftautoh.h
similarity index 74%
rename from include/ftautoh.h
rename to include/freetype/ftautoh.h
index 936791e..48ff1aa 100644
--- a/include/ftautoh.h
+++ b/include/freetype/ftautoh.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for controlling the auto-hinter (specification only).   */
 /*                                                                         */
-/*  Copyright 2012, 2013 by                                                */
+/*  Copyright 2012-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTAUTOH_H__
-#define __FTAUTOH_H__
+#ifndef FTAUTOH_H_
+#define FTAUTOH_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -219,8 +219,8 @@
    *       U+0F00 - U+0FFF  // Tibetan
    *       U+1900 - U+194F  // Limbu
    *       U+1B80 - U+1BBF  // Sundanese
-   *       U+1C80 - U+1CDF  // Meetei Mayak
    *       U+A800 - U+A82F  // Syloti Nagri
+   *       U+ABC0 - U+ABFF  // Meetei Mayek
    *      U+11800 - U+118DF // Sharada
    *     }
    *
@@ -245,12 +245,12 @@
    *   The data exchange structure for the @glyph-to-script-map property.
    *
    */
-   typedef struct  FT_Prop_GlyphToScriptMap_
-   {
-     FT_Face   face;
-     FT_Byte*  map;
+  typedef struct  FT_Prop_GlyphToScriptMap_
+  {
+    FT_Face     face;
+    FT_UShort*  map;
 
-   } FT_Prop_GlyphToScriptMap;
+  } FT_Prop_GlyphToScriptMap;
 
 
   /**************************************************************************
@@ -300,7 +300,7 @@
    * @description:
    *   *Experimental* *only*
    *
-   *   If Freetype gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
+   *   If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
    *   the HarfBuzz library access OpenType features for getting better
    *   glyph coverages, this property sets the (auto-fitter) script to be
    *   used for the default (OpenType) script data of a font's GSUB table.
@@ -384,19 +384,128 @@
    *   The data exchange structure for the @increase-x-height property.
    *
    */
-   typedef struct  FT_Prop_IncreaseXHeight_
-   {
-     FT_Face  face;
-     FT_UInt  limit;
+  typedef struct  FT_Prop_IncreaseXHeight_
+  {
+    FT_Face  face;
+    FT_UInt  limit;
 
-   } FT_Prop_IncreaseXHeight;
+  } FT_Prop_IncreaseXHeight;
 
 
- /* */
+  /**************************************************************************
+   *
+   * @property:
+   *   warping
+   *
+   * @description:
+   *   *Experimental* *only*
+   *
+   *   If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to
+   *   activate the warp hinting code in the auto-hinter, this property
+   *   switches warping on and off.
+   *
+   *   Warping only works in `light' auto-hinting mode.  The idea of the
+   *   code is to slightly scale and shift a glyph along the non-hinted
+   *   dimension (which is usually the horizontal axis) so that as much of
+   *   its segments are aligned (more or less) to the grid.  To find out a
+   *   glyph's optimal scaling and shifting value, various parameter
+   *   combinations are tried and scored.
+   *
+   *   By default, warping is off.  The example below shows how to switch on
+   *   warping (omitting the error handling).
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Bool     warping = 1;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "autofitter",
+   *                               "warping", &warping );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable (using values 1 and 0 for `on' and `off', respectively).
+   *
+   *   The warping code can also change advance widths.  Have a look at the
+   *   `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure
+   *   for details on improving inter-glyph distances while rendering.
+   *
+   *   Since warping is a global property of the auto-hinter it is best to
+   *   change its value before rendering any face.  Otherwise, you should
+   *   reload all faces that get auto-hinted in `light' hinting mode.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   no-stem-darkening[autofit]
+   *
+   * @description:
+   *   *Experimental* *only,* *requires* *linear* *alpha* *blending* *and*
+   *   *gamma* *correction*
+   *
+   *   Stem darkening emboldens glyphs at smaller sizes to make them more
+   *   readable on common low-DPI screens when using linear alpha blending
+   *   and gamma correction, see @FT_Render_Glyph.  When not using linear
+   *   alpha blending and gamma correction, glyphs will appear heavy and
+   *   fuzzy!
+   *
+   *   Gamma correction essentially lightens fonts since shades of grey are
+   *   shifted to higher pixel values (=~higher brightness) to match the
+   *   original intention to the reality of our screens.  The side-effect is
+   *   that glyphs `thin out'.  Mac OS~X and Adobe's proprietary font
+   *   rendering library implement a counter-measure: stem darkening at
+   *   smaller sizes where shades of gray dominate.  By emboldening a glyph
+   *   slightly in relation to its pixel size, individual pixels get higher
+   *   coverage of filled-in outlines and are therefore `blacker'.  This
+   *   counteracts the `thinning out' of glyphs, making text remain readable
+   *   at smaller sizes.  All glyphs that pass through the auto-hinter will
+   *   be emboldened unless this property is set to TRUE.
+   *
+   *   See the description of the CFF driver for algorithmic details.  Total
+   *   consistency with the CFF driver is currently not achieved because the
+   *   emboldening method differs and glyphs must be scaled down on the
+   *   Y-axis to keep outline points inside their precomputed blue zones.
+   *   The smaller the size (especially 9ppem and down), the higher the loss
+   *   of emboldening versus the CFF driver.
+   *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable similar to the CFF driver.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   darkening-parameters[autofit]
+   *
+   * @description:
+   *   *Experimental* *only*
+   *
+   *   See the description of the CFF driver for details.  This
+   *   implementation appropriates the
+   *   CFF_CONFIG_OPTION_DARKENING_PARAMETER_* #defines for consistency.
+   *   Note the differences described in @no-stem-darkening[autofit].
+   *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable similar to the CFF driver.
+   */
+
+
+  /* */
+
 
 FT_END_HEADER
 
-#endif /* __FTAUTOH_H__ */
+#endif /* FTAUTOH_H_ */
 
 
 /* END */
diff --git a/include/ftbbox.h b/include/freetype/ftbbox.h
similarity index 97%
rename from include/ftbbox.h
rename to include/freetype/ftbbox.h
index 8938841..2a4d214 100644
--- a/include/ftbbox.h
+++ b/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType exact bbox computation (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2007, 2011, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,8 +27,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTBBOX_H__
-#define __FTBBOX_H__
+#ifndef FTBBOX_H_
+#define FTBBOX_H_
 
 
 #include <ft2build.h>
@@ -85,13 +85,12 @@
   FT_Outline_Get_BBox( FT_Outline*  outline,
                        FT_BBox     *abbox );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTBBOX_H__ */
+#endif /* FTBBOX_H_ */
 
 
 /* END */
diff --git a/include/ftbdf.h b/include/freetype/ftbdf.h
similarity index 97%
rename from include/ftbdf.h
rename to include/freetype/ftbdf.h
index 8b3c411..016dba0 100644
--- a/include/ftbdf.h
+++ b/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for accessing BDF-specific strings (specification).     */
 /*                                                                         */
-/*  Copyright 2002-2004, 2006, 2009, 2014 by                               */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTBDF_H__
-#define __FTBDF_H__
+#ifndef FTBDF_H_
+#define FTBDF_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -53,7 +53,7 @@
   /**********************************************************************
    *
    * @enum:
-   *    FT_PropertyType
+   *    BDF_PropertyType
    *
    * @description:
    *    A list of BDF property types.
@@ -200,11 +200,11 @@
                        const char*       prop_name,
                        BDF_PropertyRec  *aproperty );
 
- /* */
+  /* */
 
 FT_END_HEADER
 
-#endif /* __FTBDF_H__ */
+#endif /* FTBDF_H_ */
 
 
 /* END */
diff --git a/include/ftbitmap.h b/include/freetype/ftbitmap.h
similarity index 92%
rename from include/ftbitmap.h
rename to include/freetype/ftbitmap.h
index 7dbf5ba..0eac7b9 100644
--- a/include/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (specification).              */
 /*                                                                         */
-/*  Copyright 2004-2006, 2008, 2013 by                                     */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTBITMAP_H__
-#define __FTBITMAP_H__
+#ifndef FTBITMAP_H_
+#define FTBITMAP_H_
 
 
 #include <ft2build.h>
@@ -45,7 +45,9 @@
   /*    Handling FT_Bitmap objects.                                        */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This section contains functions for converting FT_Bitmap objects.  */
+  /*    This section contains functions for handling @FT_Bitmap objects.   */
+  /*    Note that none of the functions changes the bitmap's `flow' (as    */
+  /*    indicated by the sign of the `pitch' field in `FT_Bitmap').        */
   /*                                                                       */
   /*************************************************************************/
 
@@ -53,7 +55,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Bitmap_New                                                      */
+  /*    FT_Bitmap_Init                                                     */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Initialize a pointer to an @FT_Bitmap structure.                   */
@@ -61,6 +63,14 @@
   /* <InOut>                                                               */
   /*    abitmap :: A pointer to the bitmap structure.                      */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    A deprecated name for the same function is `FT_Bitmap_New'.        */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Bitmap_Init( FT_Bitmap  *abitmap );
+
+
+  /* deprecated */
   FT_EXPORT( void )
   FT_Bitmap_New( FT_Bitmap  *abitmap );
 
@@ -122,6 +132,9 @@
   /*    If you want to embolden the bitmap owned by a @FT_GlyphSlotRec,    */
   /*    you should call @FT_GlyphSlot_Own_Bitmap on the slot first.        */
   /*                                                                       */
+  /*    Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format    */
+  /*    are converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp).          */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Bitmap_Embolden( FT_Library  library,
                       FT_Bitmap*  bitmap,
@@ -197,7 +210,7 @@
   /*    FT_Bitmap_Done                                                     */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Destroy a bitmap object created with @FT_Bitmap_New.               */
+  /*    Destroy a bitmap object initialized with @FT_Bitmap_Init.          */
   /*                                                                       */
   /* <Input>                                                               */
   /*    library :: A handle to a library object.                           */
@@ -221,7 +234,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTBITMAP_H__ */
+#endif /* FTBITMAP_H_ */
 
 
 /* END */
diff --git a/include/ftbzip2.h b/include/freetype/ftbzip2.h
similarity index 96%
rename from include/ftbzip2.h
rename to include/freetype/ftbzip2.h
index 1bf81b1..b7f2eee 100644
--- a/include/ftbzip2.h
+++ b/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Bzip2-compressed stream support.                                     */
 /*                                                                         */
-/*  Copyright 2010 by                                                      */
+/*  Copyright 2010-2016 by                                                 */
 /*  Joel Klinghed.                                                         */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTBZIP2_H__
-#define __FTBZIP2_H__
+#ifndef FTBZIP2_H_
+#define FTBZIP2_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -91,12 +91,12 @@
   FT_Stream_OpenBzip2( FT_Stream  stream,
                        FT_Stream  source );
 
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTBZIP2_H__ */
+#endif /* FTBZIP2_H_ */
 
 
 /* END */
diff --git a/include/ftcache.h b/include/freetype/ftcache.h
similarity index 98%
rename from include/ftcache.h
rename to include/freetype/ftcache.h
index a5d7100..883c88d 100644
--- a/include/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Cache subsystem (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010, 2013 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTCACHE_H__
-#define __FTCACHE_H__
+#ifndef FTCACHE_H_
+#define FTCACHE_H_
 
 
 #include <ft2build.h>
@@ -209,10 +209,10 @@
   typedef FT_Error
   (*FTC_Face_Requester)( FTC_FaceID  face_id,
                          FT_Library  library,
-                         FT_Pointer  request_data,
+                         FT_Pointer  req_data,
                          FT_Face*    aface );
 
- /* */
+  /* */
 
 
   /*************************************************************************/
@@ -667,8 +667,8 @@
   typedef struct  FTC_ImageTypeRec_
   {
     FTC_FaceID  face_id;
-    FT_Int      width;
-    FT_Int      height;
+    FT_UInt     width;
+    FT_UInt     height;
     FT_Int32    flags;
 
   } FTC_ImageTypeRec;
@@ -749,7 +749,7 @@
   /*    aglyph :: The corresponding @FT_Glyph object.  0~in case of        */
   /*              failure.                                                 */
   /*                                                                       */
-  /*    anode  :: Used to return the address of of the corresponding cache */
+  /*    anode  :: Used to return the address of the corresponding cache    */
   /*              node after incrementing its reference count (see note    */
   /*              below).                                                  */
   /*                                                                       */
@@ -802,7 +802,7 @@
   /*    aglyph     :: The corresponding @FT_Glyph object.  0~in case of    */
   /*                  failure.                                             */
   /*                                                                       */
-  /*    anode      :: Used to return the address of of the corresponding   */
+  /*    anode      :: Used to return the address of the corresponding      */
   /*                  cache node after incrementing its reference count    */
   /*                  (see note below).                                    */
   /*                                                                       */
@@ -957,7 +957,7 @@
   /* <Output>                                                              */
   /*    sbit   :: A handle to a small bitmap descriptor.                   */
   /*                                                                       */
-  /*    anode  :: Used to return the address of of the corresponding cache */
+  /*    anode  :: Used to return the address of the corresponding cache    */
   /*              node after incrementing its reference count (see note    */
   /*              below).                                                  */
   /*                                                                       */
@@ -1012,7 +1012,7 @@
   /* <Output>                                                              */
   /*    sbit       :: A handle to a small bitmap descriptor.               */
   /*                                                                       */
-  /*    anode      :: Used to return the address of of the corresponding   */
+  /*    anode      :: Used to return the address of the corresponding      */
   /*                  cache node after incrementing its reference count    */
   /*                  (see note below).                                    */
   /*                                                                       */
@@ -1046,12 +1046,12 @@
                               FTC_SBit      *sbit,
                               FTC_Node      *anode );
 
+  /* */
 
- /* */
 
 FT_END_HEADER
 
-#endif /* __FTCACHE_H__ */
+#endif /* FTCACHE_H_ */
 
 
 /* END */
diff --git a/include/ftcffdrv.h b/include/freetype/ftcffdrv.h
similarity index 86%
rename from include/ftcffdrv.h
rename to include/freetype/ftcffdrv.h
index e4d039d..8f88cc4 100644
--- a/include/ftcffdrv.h
+++ b/include/freetype/ftcffdrv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for controlling the CFF driver (specification only).    */
 /*                                                                         */
-/*  Copyright 2013 by                                                      */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTCFFDRV_H__
-#define __FTCFFDRV_H__
+#ifndef FTCFFDRV_H_
+#define FTCFFDRV_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -89,7 +89,7 @@
    *   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
+   *   2) Alignment 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
@@ -108,13 +108,19 @@
    *   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.
+   *
+   * @order:
+   *   hinting-engine[cff]
+   *   no-stem-darkening[cff]
+   *   darkening-parameters[cff]
+   *
    */
 
 
   /**************************************************************************
    *
    * @property:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *
    * @description:
    *   Thanks to Adobe, which contributed a new hinting (and parsing)
@@ -142,6 +148,8 @@
    * @note:
    *   This property can be used with @FT_Property_Get also.
    *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable (using values `adobe' or `freetype').
    */
 
 
@@ -151,8 +159,8 @@
    *   FT_CFF_HINTING_XXX
    *
    * @description:
-   *   A list of constants used for the @hinting-engine property to select
-   *   the hinting engine for CFF fonts.
+   *   A list of constants used for the @hinting-engine[cff] property to
+   *   select the hinting engine for CFF fonts.
    *
    * @values:
    *   FT_CFF_HINTING_FREETYPE ::
@@ -169,7 +177,7 @@
   /**************************************************************************
    *
    * @property:
-   *   no-stem-darkening
+   *   no-stem-darkening[cff]
    *
    * @description:
    *   By default, the Adobe CFF engine darkens stems at smaller sizes,
@@ -193,13 +201,16 @@
    * @note:
    *   This property can be used with @FT_Property_Get also.
    *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable (using values 1 and 0 for `on' and `off', respectively).
+   *
    */
 
 
   /**************************************************************************
    *
    * @property:
-   *   darkening-parameters
+   *   darkening-parameters[cff]
    *
    * @description:
    *   By default, the Adobe CFF engine darkens stems as follows (if the
@@ -212,9 +223,11 @@
    *     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.
+   *   and piecewise linear in-between.  At configuration time, these four
+   *   control points can be set with the macro
+   *   `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'.  At runtime, the control
+   *   points can be changed using the `darkening-parameters' property, as
+   *   the following example demonstrates.
    *
    *   {
    *     FT_Library  library;
@@ -240,15 +253,23 @@
    * @note:
    *   This property can be used with @FT_Property_Get also.
    *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable, using eight comma-separated integers without spaces.  Here
+   *   the above example, using `\' to break the line for readability.
+   *
+   *   {
+   *     FREETYPE_PROPERTIES=\
+   *     cff:darkening-parameters=500,300,1000,200,1500,100,2000,0
+   *   }
    */
 
+  /* */
 
- /* */
 
 FT_END_HEADER
 
 
-#endif /* __FTCFFDRV_H__ */
+#endif /* FTCFFDRV_H_ */
 
 
 /* END */
diff --git a/include/ftchapters.h b/include/freetype/ftchapters.h
similarity index 89%
rename from include/ftchapters.h
rename to include/freetype/ftchapters.h
index d333761..ab43895 100644
--- a/include/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -119,3 +119,17 @@
 /*    lcd_filtering                                                        */
 /*                                                                         */
 /***************************************************************************/
+
+/***************************************************************************/
+/*                                                                         */
+/* <Chapter>                                                               */
+/*    error_codes                                                          */
+/*                                                                         */
+/* <Title>                                                                 */
+/*    Error Codes                                                          */
+/*                                                                         */
+/* <Sections>                                                              */
+/*    error_enumerations                                                   */
+/*    error_code_values                                                    */
+/*                                                                         */
+/***************************************************************************/
diff --git a/include/ftcid.h b/include/freetype/ftcid.h
similarity index 93%
rename from include/ftcid.h
rename to include/freetype/ftcid.h
index 203a30c..e1bc9fe 100644
--- a/include/ftcid.h
+++ b/include/freetype/ftcid.h
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    FreeType API for accessing CID font information (specification).     */
 /*                                                                         */
-/*  Copyright 2007, 2009 by Dereg Clegg, Michael Toftdal.                  */
+/*  Copyright 2007-2016 by                                                 */
+/*  Dereg Clegg and Michael Toftdal.                                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -15,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTCID_H__
-#define __FTCID_H__
+#ifndef FTCID_H_
+#define FTCID_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -96,8 +97,8 @@
    *
    * @description:
    *    Retrieve the type of the input face, CID keyed or not.  In
-   *    constrast to the @FT_IS_CID_KEYED macro this function returns
-   *    successfully also for CID-keyed fonts in an SNFT wrapper.
+   *    contrast to the @FT_IS_CID_KEYED macro this function returns
+   *    successfully also for CID-keyed fonts in an SFNT wrapper.
    *
    * @input:
    *    face ::
@@ -156,11 +157,12 @@
                                FT_UInt   glyph_index,
                                FT_UInt  *cid );
 
- /* */
+  /* */
+
 
 FT_END_HEADER
 
-#endif /* __FTCID_H__ */
+#endif /* FTCID_H_ */
 
 
 /* END */
diff --git a/include/fterrdef.h b/include/freetype/fterrdef.h
similarity index 81%
rename from include/fterrdef.h
rename to include/freetype/fterrdef.h
index 99b2fad..3f53dd5 100644
--- a/include/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType error codes (specification).                                */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2006, 2007, 2010-2013 by                         */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,18 +16,43 @@
 /***************************************************************************/
 
 
-  /*******************************************************************/
-  /*******************************************************************/
-  /*****                                                         *****/
-  /*****                LIST OF ERROR CODES/MESSAGES             *****/
-  /*****                                                         *****/
-  /*******************************************************************/
-  /*******************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*   error_code_values                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*   Error Code Values                                                   */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*   All possible error codes returned by FreeType functions.            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   The list below is taken verbatim from the file `fterrdef.h'         */
+  /*   (loaded automatically by including `FT_FREETYPE_H').  The first     */
+  /*   argument of the `FT_ERROR_DEF_' macro is the error label; by        */
+  /*   default, the prefix `FT_Err_' gets added so that you get error      */
+  /*   names like `FT_Err_Cannot_Open_Resource'.  The second argument is   */
+  /*   the error code, and the last argument an error string, which is not */
+  /*   used by FreeType.                                                   */
+  /*                                                                       */
+  /*   Within your application you should *only* use error names and       */
+  /*   *never* its numeric values!  The latter might (and actually do)     */
+  /*   change in forthcoming FreeType versions.                            */
+  /*                                                                       */
+  /*   Macro `FT_NOERRORDEF_' defines `FT_Err_Ok', which is always zero.   */
+  /*   See the `Error Enumerations' subsection how to automatically        */
+  /*   generate a list of error strings.                                   */
+  /*                                                                       */
+  /*************************************************************************/
 
 
-  /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */
-  /* including this file.                                           */
-
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Err_XXX                                                         */
+  /*                                                                       */
+  /*************************************************************************/
 
   /* generic errors */
 
@@ -218,7 +243,7 @@
   FT_ERRORDEF_( No_Unicode_Glyph_Name,                       0xA3,
                 "no Unicode glyph name found" )
   FT_ERRORDEF_( Glyph_Too_Big,                               0xA4,
-                "glyph to big for hinting" )
+                "glyph too big for hinting" )
 
   /* BDF errors */
 
@@ -245,5 +270,7 @@
   FT_ERRORDEF_( Corrupted_Font_Glyphs,                       0xBA,
                 "Font glyphs corrupted or missing fields" )
 
+  /* */
+
 
 /* END */
diff --git a/include/freetype/fterrors.h b/include/freetype/fterrors.h
new file mode 100644
index 0000000..e15bfb0
--- /dev/null
+++ b/include/freetype/fterrors.h
@@ -0,0 +1,226 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fterrors.h                                                             */
+/*                                                                         */
+/*    FreeType error code handling (specification).                        */
+/*                                                                         */
+/*  Copyright 1996-2016 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*   error_enumerations                                                  */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*   Error Enumerations                                                  */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*   How to handle errors and error strings.                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   The header file `fterrors.h' (which is automatically included by    */
+  /*   `freetype.h' defines the handling of FreeType's enumeration         */
+  /*   constants.  It can also be used to generate error message strings   */
+  /*   with a small macro trick explained below.                           */
+  /*                                                                       */
+  /*   *Error* *Formats*                                                   */
+  /*                                                                       */
+  /*   The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be   */
+  /*   defined in `ftoption.h' in order to make the higher byte indicate   */
+  /*   the module where the error has happened (this is not compatible     */
+  /*   with standard builds of FreeType&nbsp;2, however).  See the file    */
+  /*   `ftmoderr.h' for more details.                                      */
+  /*                                                                       */
+  /*   *Error* *Message* *Strings*                                         */
+  /*                                                                       */
+  /*   Error definitions are set up with special macros that allow client  */
+  /*   applications to build a table of error message strings.  The        */
+  /*   strings are not included in a normal build of FreeType&nbsp;2 to    */
+  /*   save space (most client applications do not use them).              */
+  /*                                                                       */
+  /*   To do so, you have to define the following macros before including  */
+  /*   this file.                                                          */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     FT_ERROR_START_LIST                                               */
+  /*   }                                                                   */
+  /*                                                                       */
+  /*   This macro is called before anything else to define the start of    */
+  /*   the error list.  It is followed by several FT_ERROR_DEF calls.      */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     FT_ERROR_DEF( e, v, s )                                           */
+  /*   }                                                                   */
+  /*                                                                       */
+  /*   This macro is called to define one single error.  `e' is the error  */
+  /*   code identifier (e.g., `Invalid_Argument'), `v' is the error's      */
+  /*   numerical value, and `s' is the corresponding error string.         */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     FT_ERROR_END_LIST                                                 */
+  /*   }                                                                   */
+  /*                                                                       */
+  /*   This macro ends the list.                                           */
+  /*                                                                       */
+  /*   Additionally, you have to undefine `FTERRORS_H_' before #including  */
+  /*   this file.                                                          */
+  /*                                                                       */
+  /*   Here is a simple example.                                           */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     #undef FTERRORS_H_                                                */
+  /*     #define FT_ERRORDEF( e, v, s )  { e, s },                         */
+  /*     #define FT_ERROR_START_LIST     {                                 */
+  /*     #define FT_ERROR_END_LIST       { 0, NULL } };                    */
+  /*                                                                       */
+  /*     const struct                                                      */
+  /*     {                                                                 */
+  /*       int          err_code;                                          */
+  /*       const char*  err_msg;                                           */
+  /*     } ft_errors[] =                                                   */
+  /*                                                                       */
+  /*     #include FT_ERRORS_H                                              */
+  /*   }                                                                   */
+  /*                                                                       */
+  /*   Note that `FT_Err_Ok' is _not_ defined with `FT_ERRORDEF' but with  */
+  /*   `FT_NOERRORDEF'; it is always zero.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /* */
+
+  /* In previous FreeType versions we used `__FTERRORS_H__'.  However, */
+  /* using two successive underscores in a non-system symbol name      */
+  /* violates the C (and C++) standard, so it was changed to the       */
+  /* current form.  In spite of this, we have to make                  */
+  /*                                                                   */
+  /*   #undefine __FTERRORS_H__                                        */
+  /*                                                                   */
+  /* work for backwards compatibility.                                 */
+  /*                                                                   */
+#if !( defined( FTERRORS_H_ ) && defined ( __FTERRORS_H__ ) )
+#define FTERRORS_H_
+#define __FTERRORS_H__
+
+
+  /* include module base error codes */
+#include FT_MODULE_ERRORS_H
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                       SETUP MACROS                      *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#undef  FT_NEED_EXTERN_C
+
+
+  /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
+  /* By default, we use `FT_Err_'.                            */
+  /*                                                          */
+#ifndef FT_ERR_PREFIX
+#define FT_ERR_PREFIX  FT_Err_
+#endif
+
+
+  /* FT_ERR_BASE is used as the base for module-specific errors. */
+  /*                                                             */
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+#ifndef FT_ERR_BASE
+#define FT_ERR_BASE  FT_Mod_Err_Base
+#endif
+
+#else
+
+#undef FT_ERR_BASE
+#define FT_ERR_BASE  0
+
+#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */
+
+
+  /* If FT_ERRORDEF is not defined, we need to define a simple */
+  /* enumeration type.                                         */
+  /*                                                           */
+#ifndef FT_ERRORDEF
+
+#define FT_ERRORDEF( e, v, s )  e = v,
+#define FT_ERROR_START_LIST     enum {
+#define FT_ERROR_END_LIST       FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+  extern "C" {
+#endif
+
+#endif /* !FT_ERRORDEF */
+
+
+  /* this macro is used to define an error */
+#define FT_ERRORDEF_( e, v, s )                                             \
+          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
+
+  /* this is only used for <module>_Err_Ok, which must be 0! */
+#define FT_NOERRORDEF_( e, v, s )                             \
+          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
+
+
+#ifdef FT_ERROR_START_LIST
+  FT_ERROR_START_LIST
+#endif
+
+
+  /* now include the error codes */
+#include FT_ERROR_DEFINITIONS_H
+
+
+#ifdef FT_ERROR_END_LIST
+  FT_ERROR_END_LIST
+#endif
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                      SIMPLE CLEANUP                     *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+#ifdef FT_NEED_EXTERN_C
+  }
+#endif
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+#undef FT_ERRORDEF
+#undef FT_ERRORDEF_
+#undef FT_NOERRORDEF_
+
+#undef FT_NEED_EXTERN_C
+#undef FT_ERR_BASE
+
+  /* FT_ERR_PREFIX is needed internally */
+#ifndef FT2_BUILD_LIBRARY
+#undef FT_ERR_PREFIX
+#endif
+
+#endif /* !(FTERRORS_H_ && __FTERRORS_H__) */
+
+
+/* END */
diff --git a/include/ftxf86.h b/include/freetype/ftfntfmt.h
similarity index 78%
rename from include/ftxf86.h
rename to include/freetype/ftfntfmt.h
index 493cccd..bd42324 100644
--- a/include/ftxf86.h
+++ b/include/freetype/ftfntfmt.h
@@ -1,10 +1,10 @@
 /***************************************************************************/
 /*                                                                         */
-/*  ftxf86.h                                                               */
+/*  ftfntfmt.h                                                             */
 /*                                                                         */
-/*    Support functions for X11.                                           */
+/*    Support functions for font formats.                                  */
 /*                                                                         */
-/*  Copyright 2002-2004, 2006, 2007, 2013 by                               */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTXF86_H__
-#define __FTXF86_H__
+#ifndef FTFNTFMT_H_
+#define FTFNTFMT_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -49,22 +49,20 @@
   /*   however, there are special cases (like in PDF devices) where it is  */
   /*   important to differentiate, in spite of FreeType's uniform API.     */
   /*                                                                       */
-  /*   This function is in the X11/xf86 namespace for historical reasons   */
-  /*   and in no way depends on that windowing system.                     */
-  /*                                                                       */
   /*************************************************************************/
 
 
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*   FT_Get_X11_Font_Format                                              */
+  /*   FT_Get_Font_Format                                                  */
   /*                                                                       */
   /* <Description>                                                         */
-  /*   Return a string describing the format of a given face, using values */
-  /*   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'.                                           */
+  /*   Return a string describing the format of a given face.  Possible    */
+  /*   values are `TrueType', `Type~1', `BDF', `PCF', `Type~42',           */
+  /*   `CID~Type~1', `CFF', `PFR', and `Windows~FNT'.                      */
+  /*                                                                       */
+  /*   The return value is suitable to be used as an X11 FONT_PROPERTY.    */
   /*                                                                       */
   /* <Input>                                                               */
   /*   face ::                                                             */
@@ -73,11 +71,25 @@
   /* <Return>                                                              */
   /*   Font format string.  NULL in case of error.                         */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*   A deprecated name for the same function is                          */
+  /*   `FT_Get_X11_Font_Format'.                                           */
+  /*                                                                       */
+  FT_EXPORT( const char* )
+  FT_Get_Font_Format( FT_Face  face );
+
+
+  /* deprecated */
   FT_EXPORT( const char* )
   FT_Get_X11_Font_Format( FT_Face  face );
 
- /* */
+
+  /* */
+
 
 FT_END_HEADER
 
-#endif /* __FTXF86_H__ */
+#endif /* FTFNTFMT_H_ */
+
+
+/* END */
diff --git a/include/ftgasp.h b/include/freetype/ftgasp.h
similarity index 96%
rename from include/ftgasp.h
rename to include/freetype/ftgasp.h
index 453d4fa..3f5b3bc 100644
--- a/include/ftgasp.h
+++ b/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Access of TrueType's `gasp' table (specification).                   */
 /*                                                                         */
-/*  Copyright 2007, 2008, 2011 by                                          */
+/*  Copyright 2007-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef _FT_GASP_H_
-#define _FT_GASP_H_
+#ifndef FTGASP_H_
+#define FTGASP_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -120,9 +120,10 @@
   FT_Get_Gasp( FT_Face  face,
                FT_UInt  ppem );
 
-/* */
+  /* */
 
-#endif /* _FT_GASP_H_ */
+
+#endif /* FTGASP_H_ */
 
 
 /* END */
diff --git a/include/ftglyph.h b/include/freetype/ftglyph.h
similarity index 96%
rename from include/ftglyph.h
rename to include/freetype/ftglyph.h
index 2d30ed9..d9840a8 100644
--- a/include/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2008, 2009, 2011, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,8 +29,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTGLYPH_H__
-#define __FTGLYPH_H__
+#ifndef FTGLYPH_H_
+#define FTGLYPH_H_
 
 
 #include <ft2build.h>
@@ -325,22 +325,8 @@
   } FT_Glyph_BBox_Mode;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    ft_glyph_bbox_xxx                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    These constants are deprecated.  Use the corresponding             */
-  /*    @FT_Glyph_BBox_Mode values instead.                                */
-  /*                                                                       */
-  /* <Values>                                                              */
-  /*   ft_glyph_bbox_unscaled  :: See @FT_GLYPH_BBOX_UNSCALED.             */
-  /*   ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS.            */
-  /*   ft_glyph_bbox_gridfit   :: See @FT_GLYPH_BBOX_GRIDFIT.              */
-  /*   ft_glyph_bbox_truncate  :: See @FT_GLYPH_BBOX_TRUNCATE.             */
-  /*   ft_glyph_bbox_pixels    :: See @FT_GLYPH_BBOX_PIXELS.               */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_Glyph_BBox_Mode' values instead                   */
 #define ft_glyph_bbox_unscaled   FT_GLYPH_BBOX_UNSCALED
 #define ft_glyph_bbox_subpixels  FT_GLYPH_BBOX_SUBPIXELS
 #define ft_glyph_bbox_gridfit    FT_GLYPH_BBOX_GRIDFIT
@@ -603,13 +589,12 @@
   FT_EXPORT( FT_Error )
   FT_Matrix_Invert( FT_Matrix*  matrix );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTGLYPH_H__ */
+#endif /* FTGLYPH_H_ */
 
 
 /* END */
diff --git a/include/ftgxval.h b/include/freetype/ftgxval.h
similarity index 92%
rename from include/ftgxval.h
rename to include/freetype/ftgxval.h
index 6d38e32..a58e86a 100644
--- a/include/ftgxval.h
+++ b/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating TrueTypeGX/AAT tables (specification).   */
 /*                                                                         */
-/*  Copyright 2004-2006, 2013 by                                           */
+/*  Copyright 2004-2016 by                                                 */
 /*  Masatake YAMATO, Redhat K.K,                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
@@ -25,8 +25,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTGXVAL_H__
-#define __FTGXVAL_H__
+#ifndef FTGXVAL_H_
+#define FTGXVAL_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -57,9 +57,19 @@
   /*    some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd,  */
   /*    trak, prop, lcar).                                                 */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_TrueTypeGX_Validate                                             */
+  /*    FT_TrueTypeGX_Free                                                 */
+  /*                                                                       */
+  /*    FT_ClassicKern_Validate                                            */
+  /*    FT_ClassicKern_Free                                                */
+  /*                                                                       */
+  /*    FT_VALIDATE_GX_LENGTH                                              */
+  /*    FT_VALIDATE_GXXXX                                                  */
+  /*    FT_VALIDATE_CKERNXXX                                               */
+  /*                                                                       */
   /*************************************************************************/
 
-
   /*************************************************************************/
   /*                                                                       */
   /*                                                                       */
@@ -171,8 +181,6 @@
                           FT_VALIDATE_lcar )
 
 
-  /* */
-
  /**********************************************************************
   *
   * @function:
@@ -221,8 +229,6 @@
                           FT_UInt   table_length );
 
 
-  /* */
-
  /**********************************************************************
   *
   * @function:
@@ -248,8 +254,6 @@
                       FT_Bytes  table );
 
 
-  /* */
-
  /**********************************************************************
   *
   * @enum:
@@ -277,8 +281,6 @@
 #define FT_VALIDATE_CKERN  ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
 
 
-  /* */
-
  /**********************************************************************
   *
   * @function:
@@ -320,8 +322,6 @@
                            FT_Bytes  *ckern_table );
 
 
-  /* */
-
  /**********************************************************************
   *
   * @function:
@@ -346,13 +346,12 @@
   FT_ClassicKern_Free( FT_Face   face,
                        FT_Bytes  table );
 
-
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTGXVAL_H__ */
+#endif /* FTGXVAL_H_ */
 
 
 /* END */
diff --git a/include/ftgzip.h b/include/freetype/ftgzip.h
similarity index 91%
rename from include/ftgzip.h
rename to include/freetype/ftgzip.h
index 78e7269..3932ce6 100644
--- a/include/ftgzip.h
+++ b/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Gzip-compressed stream support.                                      */
 /*                                                                         */
-/*  Copyright 2002-2004, 2006, 2013 by                                     */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTGZIP_H__
-#define __FTGZIP_H__
+#ifndef FTGZIP_H_
+#define FTGZIP_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -117,11 +117,11 @@
   *
   * @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'.
+  *     Before calling the function, this is 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.
@@ -137,13 +137,12 @@
                       const FT_Byte*  input,
                       FT_ULong        input_len );
 
-
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTGZIP_H__ */
+#endif /* FTGZIP_H_ */
 
 
 /* END */
diff --git a/include/ftimage.h b/include/freetype/ftimage.h
similarity index 86%
rename from include/ftimage.h
rename to include/freetype/ftimage.h
index ea71a78..4f86c56 100644
--- a/include/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
 /*    FreeType glyph image formats and default raster interface            */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 1996-2010, 2013 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,12 +24,12 @@
   /*************************************************************************/
 
 
-#ifndef __FTIMAGE_H__
-#define __FTIMAGE_H__
+#ifndef FTIMAGE_H_
+#define FTIMAGE_H_
 
 
-  /* _STANDALONE_ is from ftgrays.c */
-#ifndef _STANDALONE_
+  /* STANDALONE_ is from ftgrays.c */
+#ifndef STANDALONE_
 #include <ft2build.h>
 #endif
 
@@ -193,67 +193,14 @@
   } FT_Pixel_Mode;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    ft_pixel_mode_xxx                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A list of deprecated constants.  Use the corresponding             */
-  /*    @FT_Pixel_Mode values instead.                                     */
-  /*                                                                       */
-  /* <Values>                                                              */
-  /*    ft_pixel_mode_none  :: See @FT_PIXEL_MODE_NONE.                    */
-  /*    ft_pixel_mode_mono  :: See @FT_PIXEL_MODE_MONO.                    */
-  /*    ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY.                    */
-  /*    ft_pixel_mode_pal2  :: See @FT_PIXEL_MODE_GRAY2.                   */
-  /*    ft_pixel_mode_pal4  :: See @FT_PIXEL_MODE_GRAY4.                   */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding `FT_Pixel_Mode' */
+  /* values instead.                                                       */
 #define ft_pixel_mode_none   FT_PIXEL_MODE_NONE
 #define ft_pixel_mode_mono   FT_PIXEL_MODE_MONO
 #define ft_pixel_mode_grays  FT_PIXEL_MODE_GRAY
 #define ft_pixel_mode_pal2   FT_PIXEL_MODE_GRAY2
 #define ft_pixel_mode_pal4   FT_PIXEL_MODE_GRAY4
 
- /* */
-
-#if 0
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    FT_Palette_Mode                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    THIS TYPE IS DEPRECATED.  DO NOT USE IT!                           */
-  /*                                                                       */
-  /*    An enumeration type to describe the format of a bitmap palette,    */
-  /*    used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8.               */
-  /*                                                                       */
-  /* <Values>                                                              */
-  /*    ft_palette_mode_rgb  :: The palette is an array of 3-byte RGB      */
-  /*                            records.                                   */
-  /*                                                                       */
-  /*    ft_palette_mode_rgba :: The palette is an array of 4-byte RGBA     */
-  /*                            records.                                   */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by       */
-  /*    FreeType, these types are not handled by the library itself.       */
-  /*                                                                       */
-  typedef enum  FT_Palette_Mode_
-  {
-    ft_palette_mode_rgb = 0,
-    ft_palette_mode_rgba,
-
-    ft_palette_mode_max   /* do not remove */
-
-  } FT_Palette_Mode;
-
-  /* */
-
-#endif
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -311,20 +258,15 @@
   /*                    field is intended for paletted pixel modes.  Not   */
   /*                    used currently.                                    */
   /*                                                                       */
-  /* <Note>                                                                */
-  /*   For now, the only pixel modes supported by FreeType are mono and    */
-  /*   grays.  However, drivers might be added in the future to support    */
-  /*   more `colorful' options.                                            */
-  /*                                                                       */
   typedef struct  FT_Bitmap_
   {
-    int             rows;
-    int             width;
+    unsigned int    rows;
+    unsigned int    width;
     int             pitch;
     unsigned char*  buffer;
-    short           num_grays;
-    char            pixel_mode;
-    char            palette_mode;
+    unsigned short  num_grays;
+    unsigned char   pixel_mode;
+    unsigned char   palette_mode;
     void*           palette;
 
   } FT_Bitmap;
@@ -381,7 +323,7 @@
   /*                                                                       */
   /*    flags      :: A set of bit flags used to characterize the outline  */
   /*                  and give hints to the scan-converter and hinter on   */
-  /*                  how to convert/grid-fit it.  See @FT_OUTLINE_FLAGS.  */
+  /*                  how to convert/grid-fit it.  See @FT_OUTLINE_XXX.    */
   /*                                                                       */
   /* <Note>                                                                */
   /*    The B/W rasterizer only checks bit~2 in the `tags' array for the   */
@@ -402,6 +344,8 @@
 
   } FT_Outline;
 
+  /* */
+
   /* Following limits must be consistent with */
   /* FT_Outline.{n_contours,n_points}         */
 #define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
@@ -411,7 +355,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Enum>                                                                */
-  /*    FT_OUTLINE_FLAGS                                                   */
+  /*    FT_OUTLINE_XXX                                                     */
   /*                                                                       */
   /* <Description>                                                         */
   /*    A list of bit-field constants use for the flags in an outline's    */
@@ -492,24 +436,8 @@
 #define FT_OUTLINE_SINGLE_PASS      0x200
 
 
- /*************************************************************************
-  *
-  * @enum:
-  *   ft_outline_flags
-  *
-  * @description:
-  *   These constants are deprecated.  Please use the corresponding
-  *   @FT_OUTLINE_FLAGS values.
-  *
-  * @values:
-  *   ft_outline_none            :: See @FT_OUTLINE_NONE.
-  *   ft_outline_owner           :: See @FT_OUTLINE_OWNER.
-  *   ft_outline_even_odd_fill   :: See @FT_OUTLINE_EVEN_ODD_FILL.
-  *   ft_outline_reverse_fill    :: See @FT_OUTLINE_REVERSE_FILL.
-  *   ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS.
-  *   ft_outline_high_precision  :: See @FT_OUTLINE_HIGH_PRECISION.
-  *   ft_outline_single_pass     :: See @FT_OUTLINE_SINGLE_PASS.
-  */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_OUTLINE_XXX' values instead                       */
 #define ft_outline_none             FT_OUTLINE_NONE
 #define ft_outline_owner            FT_OUTLINE_OWNER
 #define ft_outline_even_odd_fill    FT_OUTLINE_EVEN_ODD_FILL
@@ -796,22 +724,8 @@
   } FT_Glyph_Format;
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Enum>                                                                */
-  /*    ft_glyph_format_xxx                                                */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A list of deprecated constants.  Use the corresponding             */
-  /*    @FT_Glyph_Format values instead.                                   */
-  /*                                                                       */
-  /* <Values>                                                              */
-  /*    ft_glyph_format_none      :: See @FT_GLYPH_FORMAT_NONE.            */
-  /*    ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE.       */
-  /*    ft_glyph_format_bitmap    :: See @FT_GLYPH_FORMAT_BITMAP.          */
-  /*    ft_glyph_format_outline   :: See @FT_GLYPH_FORMAT_OUTLINE.         */
-  /*    ft_glyph_format_plotter   :: See @FT_GLYPH_FORMAT_PLOTTER.         */
-  /*                                                                       */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_Glyph_Format' values instead.                     */
 #define ft_glyph_format_none       FT_GLYPH_FORMAT_NONE
 #define ft_glyph_format_composite  FT_GLYPH_FORMAT_COMPOSITE
 #define ft_glyph_format_bitmap     FT_GLYPH_FORMAT_BITMAP
@@ -833,7 +747,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* A raster is a scan converter, in charge of rendering an outline into  */
-  /* a a bitmap.  This section contains the public API for rasters.        */
+  /* 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 `ftrender.h' for more       */
@@ -856,6 +770,21 @@
   /* <Description>                                                         */
   /*    This section contains technical definitions.                       */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Raster                                                          */
+  /*    FT_Span                                                            */
+  /*    FT_SpanFunc                                                        */
+  /*                                                                       */
+  /*    FT_Raster_Params                                                   */
+  /*    FT_RASTER_FLAG_XXX                                                 */
+  /*                                                                       */
+  /*    FT_Raster_NewFunc                                                  */
+  /*    FT_Raster_DoneFunc                                                 */
+  /*    FT_Raster_ResetFunc                                                */
+  /*    FT_Raster_SetModeFunc                                              */
+  /*    FT_Raster_RenderFunc                                               */
+  /*    FT_Raster_Funcs                                                    */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -865,8 +794,8 @@
   /*    FT_Raster                                                          */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A handle (pointer) to a raster object.  Each object can be used    */
-  /*    independently to convert an outline into a bitmap or pixmap.       */
+  /*    An opaque handle (pointer) to a raster object.  Each object can be */
+  /*    used independently to convert an outline into a bitmap or pixmap.  */
   /*                                                                       */
   typedef struct FT_RasterRec_*  FT_Raster;
 
@@ -877,8 +806,8 @@
   /*    FT_Span                                                            */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A structure used to model a single span of gray (or black) pixels  */
-  /*    when rendering a monochrome or anti-aliased bitmap.                */
+  /*    A structure used to model a single span of gray pixels when        */
+  /*    rendering an anti-aliased bitmap.                                  */
   /*                                                                       */
   /* <Fields>                                                              */
   /*    x        :: The span's horizontal start position.                  */
@@ -886,8 +815,7 @@
   /*    len      :: The span's length in pixels.                           */
   /*                                                                       */
   /*    coverage :: The span color/coverage, ranging from 0 (background)   */
-  /*                to 255 (foreground).  Only used for anti-aliased       */
-  /*                rendering.                                             */
+  /*                to 255 (foreground).                                   */
   /*                                                                       */
   /* <Note>                                                                */
   /*    This structure is used by the span drawing callback type named     */
@@ -932,16 +860,6 @@
   /*    This can be used to write anti-aliased outlines directly to a      */
   /*    given background bitmap, and even perform translucency.            */
   /*                                                                       */
-  /*    Note that the `count' field cannot be greater than a fixed value   */
-  /*    defined by the `FT_MAX_GRAY_SPANS' configuration macro in          */
-  /*    `ftoption.h'.  By default, this value is set to~32, which means    */
-  /*    that if there are more than 32~spans on a given scanline, the      */
-  /*    callback is called several times with the same `y' parameter in    */
-  /*    order to draw all callbacks.                                       */
-  /*                                                                       */
-  /*    Otherwise, the callback is only called once per scan-line, and     */
-  /*    only for those scanlines that do have `gray' pixels on them.       */
-  /*                                                                       */
   typedef void
   (*FT_SpanFunc)( int             y,
                   int             count,
@@ -957,22 +875,7 @@
   /*    FT_Raster_BitTest_Func                                             */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    THIS TYPE IS DEPRECATED.  DO NOT USE IT.                           */
-  /*                                                                       */
-  /*    A function used as a call-back by the monochrome scan-converter    */
-  /*    to test whether a given target pixel is already set to the drawing */
-  /*    `color'.  These tests are crucial to implement drop-out control    */
-  /*    per-se the TrueType spec.                                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    y     :: The pixel's y~coordinate.                                 */
-  /*                                                                       */
-  /*    x     :: The pixel's x~coordinate.                                 */
-  /*                                                                       */
-  /*    user  :: User-supplied data that is passed to the callback.        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*   1~if the pixel is `set', 0~otherwise.                               */
+  /*    Deprecated, unimplemented.                                         */
   /*                                                                       */
   typedef int
   (*FT_Raster_BitTest_Func)( int    y,
@@ -986,21 +889,7 @@
   /*    FT_Raster_BitSet_Func                                              */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    THIS TYPE IS DEPRECATED.  DO NOT USE IT.                           */
-  /*                                                                       */
-  /*    A function used as a call-back by the monochrome scan-converter    */
-  /*    to set an individual target pixel.  This is crucial to implement   */
-  /*    drop-out control according to the TrueType specification.          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    y     :: The pixel's y~coordinate.                                 */
-  /*                                                                       */
-  /*    x     :: The pixel's x~coordinate.                                 */
-  /*                                                                       */
-  /*    user  :: User-supplied data that is passed to the callback.        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    1~if the pixel is `set', 0~otherwise.                              */
+  /*    Deprecated, unimplemented.                                         */
   /*                                                                       */
   typedef void
   (*FT_Raster_BitSet_Func)( int    y,
@@ -1034,8 +923,8 @@
   /*                              pixmap's buffer _must_ be zeroed before  */
   /*                              rendering.                               */
   /*                                                                       */
-  /*                              Note that for now, direct rendering is   */
-  /*                              only possible with anti-aliased glyphs.  */
+  /*                              Direct rendering is only possible with   */
+  /*                              anti-aliased glyphs.                     */
   /*                                                                       */
   /*    FT_RASTER_FLAG_CLIP    :: This flag is only used in direct         */
   /*                              rendering mode.  If set, the output will */
@@ -1053,7 +942,8 @@
 #define FT_RASTER_FLAG_DIRECT   0x2
 #define FT_RASTER_FLAG_CLIP     0x4
 
-  /* deprecated */
+  /* these constants are deprecated; use the corresponding */
+  /* `FT_RASTER_FLAG_XXX' values instead                   */
 #define ft_raster_flag_default  FT_RASTER_FLAG_DEFAULT
 #define ft_raster_flag_aa       FT_RASTER_FLAG_AA
 #define ft_raster_flag_direct   FT_RASTER_FLAG_DIRECT
@@ -1079,11 +969,11 @@
   /*                                                                       */
   /*    gray_spans  :: The gray span drawing callback.                     */
   /*                                                                       */
-  /*    black_spans :: The black span drawing callback.  UNIMPLEMENTED!    */
+  /*    black_spans :: Unused.                                             */
   /*                                                                       */
-  /*    bit_test    :: The bit test callback.  UNIMPLEMENTED!              */
+  /*    bit_test    :: Unused.                                             */
   /*                                                                       */
-  /*    bit_set     :: The bit set callback.  UNIMPLEMENTED!               */
+  /*    bit_set     :: Unused.                                             */
   /*                                                                       */
   /*    user        :: User-supplied data that is passed to each drawing   */
   /*                   callback.                                           */
@@ -1100,15 +990,9 @@
   /*                                                                       */
   /*    If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the      */
   /*    raster will call the `gray_spans' callback to draw gray pixel      */
-  /*    spans, in the case of an aa glyph bitmap, it will call             */
-  /*    `black_spans', and `bit_test' and `bit_set' in the case of a       */
-  /*    monochrome bitmap.  This allows direct composition over a          */
-  /*    pre-existing bitmap through user-provided callbacks to perform the */
-  /*    span drawing/composition.                                          */
-  /*                                                                       */
-  /*    Note that the `bit_test' and `bit_set' callbacks are required when */
-  /*    rendering a monochrome bitmap, as they are crucial to implement    */
-  /*    correct drop-out control as defined in the TrueType specification. */
+  /*    spans.  This allows direct composition over a pre-existing bitmap  */
+  /*    through user-provided callbacks to perform the span drawing and    */
+  /*    composition.    Not supported by the monochrome rasterizer.        */
   /*                                                                       */
   typedef struct  FT_Raster_Params_
   {
@@ -1116,9 +1000,9 @@
     const void*             source;
     int                     flags;
     FT_SpanFunc             gray_spans;
-    FT_SpanFunc             black_spans;  /* doesn't work! */
-    FT_Raster_BitTest_Func  bit_test;     /* doesn't work! */
-    FT_Raster_BitSet_Func   bit_set;      /* doesn't work! */
+    FT_SpanFunc             black_spans;  /* unused */
+    FT_Raster_BitTest_Func  bit_test;     /* unused */
+    FT_Raster_BitSet_Func   bit_set;      /* unused */
     void*                   user;
     FT_BBox                 clip_box;
 
@@ -1179,10 +1063,10 @@
   /*    FT_Raster_ResetFunc                                                */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    FreeType provides an area of memory called the `render pool',      */
-  /*    available to all registered rasters.  This pool can be freely used */
-  /*    during a given scan-conversion but is shared by all rasters.  Its  */
-  /*    content is thus transient.                                         */
+  /*    FreeType used to provide an area of memory called the `render      */
+  /*    pool' available to all registered rasters.  This was not thread    */
+  /*    safe however and now FreeType never allocates this pool.  NULL     */
+  /*    is always passed in as pool_base.                                  */
   /*                                                                       */
   /*    This function is called each time the render pool changes, or just */
   /*    after a new raster object is created.                              */
@@ -1195,10 +1079,9 @@
   /*    pool_size :: The size in bytes of the render pool.                 */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    Rasters can ignore the render pool and rely on dynamic memory      */
+  /*    Rasters should ignore the render pool and rely on dynamic or stack */
   /*    allocation if they want to (a handle to the memory allocator is    */
-  /*    passed to the raster constructor).  However, this is not           */
-  /*    recommended for efficiency purposes.                               */
+  /*    passed to the raster constructor).                                 */
   /*                                                                       */
   typedef void
   (*FT_Raster_ResetFunc)( FT_Raster       raster,
@@ -1305,13 +1188,12 @@
 
   } FT_Raster_Funcs;
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTIMAGE_H__ */
+#endif /* FTIMAGE_H_ */
 
 
 /* END */
diff --git a/include/ftincrem.h b/include/freetype/ftincrem.h
similarity index 98%
rename from include/ftincrem.h
rename to include/freetype/ftincrem.h
index aaf689f..46b58b7 100644
--- a/include/ftincrem.h
+++ b/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType incremental loading (specification).                        */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2006, 2007, 2008, 2010 by                        */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTINCREM_H__
-#define __FTINCREM_H__
+#ifndef FTINCREM_H_
+#define FTINCREM_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -45,7 +45,7 @@
    * @description:
    *   This section contains various functions used to perform so-called
    *   `incremental' glyph loading.  This is a mode where all glyphs loaded
-   *   from a given @FT_Face are provided by the client application,
+   *   from a given @FT_Face are provided by the client application.
    *
    *   Apart from that, all other tables are loaded normally from the font
    *   file.  This mode is useful when FreeType is used within another
@@ -345,9 +345,10 @@
 
   /* */
 
+
 FT_END_HEADER
 
-#endif /* __FTINCREM_H__ */
+#endif /* FTINCREM_H_ */
 
 
 /* END */
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
new file mode 100644
index 0000000..e06a895
--- /dev/null
+++ b/include/freetype/ftlcdfil.h
@@ -0,0 +1,286 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlcdfil.h                                                             */
+/*                                                                         */
+/*    FreeType API for color filtering of subpixel bitmap glyphs           */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2006-2016 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 FTLCDFIL_H_
+#define FTLCDFIL_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:
+   *   lcd_filtering
+   *
+   * @title:
+   *   LCD Filtering
+   *
+   * @abstract:
+   *   Reduce color fringes of subpixel-rendered bitmaps.
+   *
+   * @description:
+   *   Subpixel rendering exploits the color-striped structure of LCD
+   *   pixels, increasing the available resolution in the direction of the
+   *   stripe (usually horizontal RGB) by a factor of~3.  Since these
+   *   subpixels are color pixels, using them unfiltered creates severe
+   *   color fringes.  Use the @FT_Library_SetLcdFilter API to specify a
+   *   low-pass filter, which is then applied to subpixel-rendered bitmaps
+   *   generated through @FT_Render_Glyph.  The filter sacrifices some of
+   *   the higher resolution to reduce color fringes, making the glyph image
+   *   slightly blurrier.  Positional improvements will remain.
+   *
+   *   Note that no filter is active by default, and that this function is
+   *   *not* implemented in default builds of the library.  You need to
+   *   #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
+   *   in order to activate it and explicitly call @FT_Library_SetLcdFilter
+   *   to enable it.
+   *
+   *   A filter should have two properties:
+   *
+   *   1) It should be normalized, meaning the sum of the 5~components
+   *      should be 256 (0x100).  It is possible to go above or under this
+   *      target sum, however: going under means tossing out contrast, going
+   *      over means invoking clamping and thereby non-linearities that
+   *      increase contrast somewhat at the expense of greater distortion
+   *      and color-fringing.  Contrast is better enhanced through stem
+   *      darkening.
+   *
+   *   2) It should be color-balanced, meaning a filter `{~a, b, c, b, a~}'
+   *      where a~+ b~=~c.  It distributes the computed coverage for one
+   *      subpixel to all subpixels equally, sacrificing some won resolution
+   *      but drastically reducing color-fringing.  Positioning improvements
+   *      remain!  Note that color-fringing can only really be minimized
+   *      when using a color-balanced filter and alpha-blending the glyph
+   *      onto a surface in linear space; see @FT_Render_Glyph.
+   *
+   *   Regarding the form, a filter can be a `boxy' filter or a `beveled'
+   *   filter.  Boxy filters are sharper but are less forgiving of non-ideal
+   *   gamma curves of a screen (viewing angles!), beveled filters are
+   *   fuzzier but more tolerant.
+   *
+   *   Examples:
+   *
+   *   - [0x10 0x40 0x70 0x40 0x10] is beveled and neither balanced nor
+   *     normalized.
+   *
+   *   - [0x1A 0x33 0x4D 0x33 0x1A] is beveled and balanced but not
+   *     normalized.
+   *
+   *   - [0x19 0x33 0x66 0x4c 0x19] is beveled and normalized but not
+   *     balanced.
+   *
+   *   - [0x00 0x4c 0x66 0x4c 0x00] is boxily beveled and normalized but not
+   *     balanced.
+   *
+   *   - [0x00 0x55 0x56 0x55 0x00] is boxy, normalized, and almost
+   *     balanced.
+   *
+   *   - [0x08 0x4D 0x56 0x4D 0x08] is beveled, normalized and, almost
+   *     balanced.
+   *
+   *   The filter affects glyph bitmaps rendered through @FT_Render_Glyph,
+   *   @FT_Load_Glyph, and @FT_Load_Char.  It does _not_ affect the output
+   *   of @FT_Outline_Render and @FT_Outline_Get_Bitmap.
+   *
+   *   If this feature is activated, the dimensions of LCD glyph bitmaps are
+   *   either wider or taller than the dimensions of the corresponding
+   *   outline with regard to the pixel grid.  For example, for
+   *   @FT_RENDER_MODE_LCD, the filter adds 3~subpixels to the left, and
+   *   3~subpixels to the right.  The bitmap offset values are adjusted
+   *   accordingly, so clients shouldn't need to modify their layout and
+   *   glyph positioning code when enabling the filter.
+   *
+   *   It is important to understand that linear alpha blending and gamma
+   *   correction is critical for correctly rendering glyphs onto surfaces
+   *   without artifacts and even more critical when subpixel rendering is
+   *   involved.
+   *
+   *   Each of the 3~alpha values (subpixels) is independently used to blend
+   *   one color channel.  That is, red alpha blends the red channel of the
+   *   text color with the red channel of the background pixel.  The
+   *   distribution of density values by the color-balanced filter assumes
+   *   alpha blending is done in linear space; only then color artifacts
+   *   cancel out.
+   */
+
+
+  /****************************************************************************
+   *
+   * @enum:
+   *   FT_LcdFilter
+   *
+   * @description:
+   *   A list of values to identify various types of LCD filters.
+   *
+   * @values:
+   *   FT_LCD_FILTER_NONE ::
+   *     Do not perform filtering.  When used with subpixel rendering, this
+   *     results in sometimes severe color fringes.
+   *
+   *   FT_LCD_FILTER_DEFAULT ::
+   *     The default filter reduces color fringes considerably, at the cost
+   *     of a slight blurriness in the output.
+   *
+   *     It is a beveled, normalized, and color-balanced five-tap filter
+   *     that is more forgiving to screens with non-ideal gamma curves and
+   *     viewing angles.  Note that while color-fringing is reduced, it can
+   *     only be minimized by using linear alpha blending and gamma
+   *     correction to render glyphs onto surfaces.  The default filter
+   *     weights are [0x08 0x4D 0x56 0x4D 0x08].
+   *
+   *   FT_LCD_FILTER_LIGHT ::
+   *     The light filter is a variant that is sharper at the cost of
+   *     slightly more color fringes than the default one.
+   *
+   *     It is a boxy, normalized, and color-balanced three-tap filter that
+   *     is less forgiving to screens with non-ideal gamma curves and
+   *     viewing angles.  This filter works best when the rendering system
+   *     uses linear alpha blending and gamma correction to render glyphs
+   *     onto surfaces.  The light filter weights are
+   *     [0x00 0x55 0x56 0x55 0x00].
+   *
+   *   FT_LCD_FILTER_LEGACY ::
+   *     This filter corresponds to the original libXft color filter.  It
+   *     provides high contrast output but can exhibit really bad color
+   *     fringes if glyphs are not extremely well hinted to the pixel grid.
+   *     In other words, it only works well if the TrueType bytecode
+   *     interpreter is enabled *and* high-quality hinted fonts are used.
+   *
+   *     This filter is only provided for comparison purposes, and might be
+   *     disabled or stay unsupported in the future.
+   *
+   *   FT_LCD_FILTER_LEGACY1 ::
+   *     For historical reasons, the FontConfig library returns a different
+   *     enumeration value for legacy LCD filtering.  To make code work that
+   *     (incorrectly) forwards FontConfig's enumeration value to
+   *     @FT_Library_SetLcdFilter without proper mapping, it is thus easiest
+   *     to have another enumeration value, which is completely equal to
+   *     `FT_LCD_FILTER_LEGACY'.
+   *
+   * @since:
+   *   2.3.0 (`FT_LCD_FILTER_LEGACY1' since 2.6.2)
+   */
+  typedef enum  FT_LcdFilter_
+  {
+    FT_LCD_FILTER_NONE    = 0,
+    FT_LCD_FILTER_DEFAULT = 1,
+    FT_LCD_FILTER_LIGHT   = 2,
+    FT_LCD_FILTER_LEGACY1 = 3,
+    FT_LCD_FILTER_LEGACY  = 16,
+
+    FT_LCD_FILTER_MAX   /* do not remove */
+
+  } FT_LcdFilter;
+
+
+  /**************************************************************************
+   *
+   * @func:
+   *   FT_Library_SetLcdFilter
+   *
+   * @description:
+   *   This function is used to apply color filtering to LCD decimated
+   *   bitmaps, like the ones used when calling @FT_Render_Glyph with
+   *   @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V.
+   *
+   * @input:
+   *   library ::
+   *     A handle to the target library instance.
+   *
+   *   filter ::
+   *     The filter type.
+   *
+   *     You can use @FT_LCD_FILTER_NONE here to disable this feature, or
+   *     @FT_LCD_FILTER_DEFAULT to use a default filter that should work
+   *     well on most LCD screens.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *   This feature is always disabled by default.  Clients must make an
+   *   explicit call to this function with a `filter' value other than
+   *   @FT_LCD_FILTER_NONE in order to enable it.
+   *
+   *   Due to *PATENTS* covering subpixel rendering, this function doesn't
+   *   do anything except returning `FT_Err_Unimplemented_Feature' if the
+   *   configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
+   *   defined in your build of the library, which should correspond to all
+   *   default builds of FreeType.
+   *
+   * @since:
+   *   2.3.0
+   */
+  FT_EXPORT( FT_Error )
+  FT_Library_SetLcdFilter( FT_Library    library,
+                           FT_LcdFilter  filter );
+
+
+  /**************************************************************************
+   *
+   * @func:
+   *   FT_Library_SetLcdFilterWeights
+   *
+   * @description:
+   *   This function can be used to enable LCD filter with custom weights,
+   *   instead of using presets in @FT_Library_SetLcdFilter.
+   *
+   * @input:
+   *   library ::
+   *     A handle to the target library instance.
+   *
+   *   weights ::
+   *     A pointer to an array; the function copies the first five bytes and
+   *     uses them to specify the filter weights.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *   Due to *PATENTS* covering subpixel rendering, this function doesn't
+   *   do anything except returning `FT_Err_Unimplemented_Feature' if the
+   *   configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
+   *   defined in your build of the library, which should correspond to all
+   *   default builds of FreeType.
+   *
+   * @since:
+   *   2.4.0
+   */
+  FT_EXPORT( FT_Error )
+  FT_Library_SetLcdFilterWeights( FT_Library      library,
+                                  unsigned char  *weights );
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLCDFIL_H_ */
+
+
+/* END */
diff --git a/include/ftlist.h b/include/freetype/ftlist.h
similarity index 98%
rename from include/ftlist.h
rename to include/freetype/ftlist.h
index 241e21e..82f437a 100644
--- a/include/ftlist.h
+++ b/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Generic list support for FreeType (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2007, 2010, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,8 +24,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTLIST_H__
-#define __FTLIST_H__
+#ifndef FTLIST_H_
+#define FTLIST_H_
 
 
 #include <ft2build.h>
@@ -248,7 +248,7 @@
   /*    list    :: A handle to the list.                                   */
   /*                                                                       */
   /*    destroy :: A list destructor that will be applied to each element  */
-  /*               of the list.                                            */
+  /*               of the list.  Set this to NULL if not needed.           */
   /*                                                                       */
   /*    memory  :: The current memory object that handles deallocation.    */
   /*                                                                       */
@@ -265,13 +265,12 @@
                     FT_Memory           memory,
                     void*               user );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTLIST_H__ */
+#endif /* FTLIST_H_ */
 
 
 /* END */
diff --git a/include/ftlzw.h b/include/freetype/ftlzw.h
similarity index 96%
rename from include/ftlzw.h
rename to include/freetype/ftlzw.h
index 00d4016..582e2c1 100644
--- a/include/ftlzw.h
+++ b/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    LZW-compressed stream support.                                       */
 /*                                                                         */
-/*  Copyright 2004, 2006 by                                                */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTLZW_H__
-#define __FTLZW_H__
+#ifndef FTLZW_H_
+#define FTLZW_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -88,12 +88,12 @@
   FT_Stream_OpenLZW( FT_Stream  stream,
                      FT_Stream  source );
 
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTLZW_H__ */
+#endif /* FTLZW_H_ */
 
 
 /* END */
diff --git a/include/ftmac.h b/include/freetype/ftmac.h
similarity index 98%
rename from include/ftmac.h
rename to include/freetype/ftmac.h
index 42874fe..adb15ca 100644
--- a/include/ftmac.h
+++ b/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Additional Mac-specific API.                                         */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2006, 2007, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,8 +25,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTMAC_H__
-#define __FTMAC_H__
+#ifndef FTMAC_H_
+#define FTMAC_H_
 
 
 #include <ft2build.h>
@@ -268,7 +268,7 @@
 FT_END_HEADER
 
 
-#endif /* __FTMAC_H__ */
+#endif /* FTMAC_H_ */
 
 
 /* END */
diff --git a/include/ftmm.h b/include/freetype/ftmm.h
similarity index 89%
rename from include/ftmm.h
rename to include/freetype/ftmm.h
index 837975a..b5d6858 100644
--- a/include/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Multiple Master font interface (specification).             */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2006, 2009, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTMM_H__
-#define __FTMM_H__
+#ifndef FTMM_H_
+#define FTMM_H_
 
 
 #include <ft2build.h>
@@ -95,8 +95,8 @@
   /*                                                                       */
   /*    num_designs :: Number of designs; should be normally 2^num_axis    */
   /*                   even though the Type~1 specification strangely      */
-  /*                   allows for intermediate designs to be present. This */
-  /*                   number cannot exceed~16.                            */
+  /*                   allows for intermediate designs to be present.      */
+  /*                   This number cannot exceed~16.                       */
   /*                                                                       */
   /*    axis        :: A table of axis descriptors.                        */
   /*                                                                       */
@@ -195,17 +195,25 @@
   /*                       (where every glyph could have a different       */
   /*                       number of designs).                             */
   /*                                                                       */
-  /*    num_namedstyles :: The number of named styles; only meaningful for */
-  /*                       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'.   */
+  /*    num_namedstyles :: The number of named styles; a `named style' is  */
+  /*                       a tuple of design coordinates that has a string */
+  /*                       ID (in the `name' table) associated with it.    */
+  /*                       The font can tell the user that, for example,   */
+  /*                       [Weight=1.5,Width=1.1] is `Bold'.               */
   /*                                                                       */
-  /*    axis            :: A table of axis descriptors.                    */
+  /*                       For Type 1 Multiple Masters fonts, this value   */
+  /*                       is always zero because the format does not      */
+  /*                       support named styles.                           */
+  /*                                                                       */
+  /*    axis            :: An axis descriptor table.                       */
   /*                       GX fonts contain slightly more data than MM.    */
+  /*                       Memory management of this pointer is done       */
+  /*                       internally by FreeType.                         */
   /*                                                                       */
-  /*    namedstyles     :: A table of named styles.                        */
+  /*    namedstyle      :: A named style table.                            */
   /*                       Only meaningful with GX.                        */
+  /*                       Memory management of this pointer is done       */
+  /*                       internally by FreeType.                         */
   /*                                                                       */
   typedef struct  FT_MM_Var_
   {
@@ -218,9 +226,6 @@
   } FT_MM_Var;
 
 
-  /* */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -258,7 +263,8 @@
   /*                                                                       */
   /* <Output>                                                              */
   /*    amaster :: The Multiple Masters/GX var descriptor.                 */
-  /*               Allocates a data structure, which the user must free.   */
+  /*               Allocates a data structure, which the user must         */
+  /*               deallocate with `free' after use.                       */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -283,8 +289,10 @@
   /*    face       :: A handle to the source face.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    num_coords :: The number of design coordinates (must be equal to   */
-  /*                  the number of axes in the font).                     */
+  /*    num_coords :: The number of available design coordinates.  If it   */
+  /*                  is larger than the number of axes, ignore the excess */
+  /*                  values.  If it is smaller than the number of axes,   */
+  /*                  use default values for the remaining axes.           */
   /*                                                                       */
   /*    coords     :: An array of design coordinates.                      */
   /*                                                                       */
@@ -310,8 +318,10 @@
   /*    face       :: A handle to the source face.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    num_coords :: The number of design coordinates (must be equal to   */
-  /*                  the number of axes in the font).                     */
+  /*    num_coords :: The number of available design coordinates.  If it   */
+  /*                  is larger than the number of axes, ignore the excess */
+  /*                  values.  If it is smaller than the number of axes,   */
+  /*                  use default values for the remaining axes.           */
   /*                                                                       */
   /*    coords     :: An array of design coordinates.                      */
   /*                                                                       */
@@ -337,8 +347,10 @@
   /*    face       :: A handle to the source face.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    num_coords :: The number of design coordinates (must be equal to   */
-  /*                  the number of axes in the font).                     */
+  /*    num_coords :: The number of available design coordinates.  If it   */
+  /*                  is larger than the number of axes, ignore the excess */
+  /*                  values.  If it is smaller than the number of axes,   */
+  /*                  use default values for the remaining axes.           */
   /*                                                                       */
   /*    coords     :: The design coordinates array (each element must be   */
   /*                  between 0 and 1.0).                                  */
@@ -365,13 +377,12 @@
                                 FT_UInt    num_coords,
                                 FT_Fixed*  coords );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTMM_H__ */
+#endif /* FTMM_H_ */
 
 
 /* END */
diff --git a/include/ftmodapi.h b/include/freetype/ftmodapi.h
similarity index 90%
rename from include/ftmodapi.h
rename to include/freetype/ftmodapi.h
index 22878f8..b4d2758 100644
--- a/include/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType modules public interface (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2008-2010, 2012, 2013 by                    */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTMODAPI_H__
-#define __FTMODAPI_H__
+#ifndef FTMODAPI_H_
+#define FTMODAPI_H_
 
 
 #include <ft2build.h>
@@ -63,7 +63,7 @@
   /*      psaux                                                            */
   /*      pshinter                                                         */
   /*      psnames                                                          */
-  /*      raster1, raster5                                                 */
+  /*      raster1                                                          */
   /*      sfnt                                                             */
   /*      smooth, smooth-lcd, smooth-lcdv                                  */
   /*      truetype                                                         */
@@ -75,6 +75,33 @@
   /*                                                                       */
   /*    Note that the FreeType Cache sub-system is not a FreeType module.  */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Module                                                          */
+  /*    FT_Module_Constructor                                              */
+  /*    FT_Module_Destructor                                               */
+  /*    FT_Module_Requester                                                */
+  /*    FT_Module_Class                                                    */
+  /*                                                                       */
+  /*    FT_Add_Module                                                      */
+  /*    FT_Get_Module                                                      */
+  /*    FT_Remove_Module                                                   */
+  /*    FT_Add_Default_Modules                                             */
+  /*                                                                       */
+  /*    FT_Property_Set                                                    */
+  /*    FT_Property_Get                                                    */
+  /*                                                                       */
+  /*    FT_New_Library                                                     */
+  /*    FT_Done_Library                                                    */
+  /*    FT_Reference_Library                                               */
+  /*                                                                       */
+  /*    FT_Renderer                                                        */
+  /*    FT_Renderer_Class                                                  */
+  /*                                                                       */
+  /*    FT_Get_Renderer                                                    */
+  /*    FT_Set_Renderer                                                    */
+  /*                                                                       */
+  /*    FT_Set_Debug_Hook                                                  */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -84,12 +111,14 @@
 #define FT_MODULE_HINTER              4  /* this module is a glyph hinter */
 #define FT_MODULE_STYLER              8  /* this module is a styler       */
 
-#define FT_MODULE_DRIVER_SCALABLE     0x100   /* the driver supports      */
+#define FT_MODULE_DRIVER_SCALABLE      0x100  /* the driver supports      */
                                               /* scalable fonts           */
-#define FT_MODULE_DRIVER_NO_OUTLINES  0x200   /* the driver does not      */
+#define FT_MODULE_DRIVER_NO_OUTLINES   0x200  /* the driver does not      */
                                               /* support vector outlines  */
-#define FT_MODULE_DRIVER_HAS_HINTER   0x400   /* the driver provides its  */
+#define FT_MODULE_DRIVER_HAS_HINTER    0x400  /* the driver provides its  */
                                               /* own hinter               */
+#define FT_MODULE_DRIVER_HINTS_LIGHTLY 0x800  /* the driver's hinter      */
+                                              /* produces LIGHT hints     */
 
 
   /* deprecated values */
@@ -98,9 +127,10 @@
 #define ft_module_hinter              FT_MODULE_HINTER
 #define ft_module_styler              FT_MODULE_STYLER
 
-#define ft_module_driver_scalable     FT_MODULE_DRIVER_SCALABLE
-#define ft_module_driver_no_outlines  FT_MODULE_DRIVER_NO_OUTLINES
-#define ft_module_driver_has_hinter   FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_scalable       FT_MODULE_DRIVER_SCALABLE
+#define ft_module_driver_no_outlines    FT_MODULE_DRIVER_NO_OUTLINES
+#define ft_module_driver_has_hinter     FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_hints_lightly  FT_MODULE_DRIVER_HINTS_LIGHTLY
 
 
   typedef FT_Pointer  FT_Module_Interface;
@@ -442,7 +472,9 @@
   /* <Description>                                                         */
   /*    This function is used to create a new FreeType library instance    */
   /*    from a given memory object.  It is thus possible to use libraries  */
-  /*    with distinct memory allocators within the same program.           */
+  /*    with distinct memory allocators within the same program.  Note,    */
+  /*    however, that the used @FT_Memory structure is expected to remain  */
+  /*    valid for the life of the @FT_Library object.                      */
   /*                                                                       */
   /*    Normally, you would call this function (followed by a call to      */
   /*    @FT_Add_Default_Modules or a series of calls to @FT_Add_Module)    */
@@ -491,7 +523,7 @@
   FT_EXPORT( FT_Error )
   FT_Done_Library( FT_Library  library );
 
-/* */
+  /* */
 
   typedef void
   (*FT_DebugHook_Func)( void*  arg );
@@ -581,12 +613,7 @@
    *       The library doesn't implement any kind of bytecode interpreter.
    *
    *     FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::
-   *       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 that position and
-   *       scale glyph components with bytecode instructions.  It produces
-   *       bad output for most other fonts.
+   *       Deprecated and removed.
    *
    *     FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
    *       The library implements a bytecode interpreter that covers
@@ -629,13 +656,12 @@
   FT_EXPORT( FT_TrueTypeEngineType )
   FT_Get_TrueType_Engine_Type( FT_Library  library );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTMODAPI_H__ */
+#endif /* FTMODAPI_H_ */
 
 
 /* END */
diff --git a/include/ftmoderr.h b/include/freetype/ftmoderr.h
similarity index 97%
rename from include/ftmoderr.h
rename to include/freetype/ftmoderr.h
index 5a27db1..2a7671c 100644
--- a/include/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType module error offsets (specification).                       */
 /*                                                                         */
-/*  Copyright 2001-2005, 2010, 2013 by                                     */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -74,7 +74,7 @@
   /* with something like                                                   */
   /*                                                                       */
   /*   {                                                                   */
-  /*     #undef __FTMODERR_H__                                             */
+  /*     #undef FTMODERR_H_                                                */
   /*     #define FT_MODERRDEF( e, v, s )  { FT_Mod_Err_ ## e, s },         */
   /*     #define FT_MODERR_START_LIST     {                                */
   /*     #define FT_MODERR_END_LIST       { 0, 0 } };                      */
@@ -91,8 +91,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTMODERR_H__
-#define __FTMODERR_H__
+#ifndef FTMODERR_H_
+#define FTMODERR_H_
 
 
   /*******************************************************************/
@@ -188,7 +188,7 @@
 #undef FT_NEED_EXTERN_C
 
 
-#endif /* __FTMODERR_H__ */
+#endif /* FTMODERR_H_ */
 
 
 /* END */
diff --git a/include/ftotval.h b/include/freetype/ftotval.h
similarity index 88%
rename from include/ftotval.h
rename to include/freetype/ftotval.h
index bb52dc4..3e6e18d 100644
--- a/include/ftotval.h
+++ b/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating OpenType tables (specification).         */
 /*                                                                         */
-/*  Copyright 2004-2007, 2013 by                                           */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,8 +27,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTOTVAL_H__
-#define __FTOTVAL_H__
+#ifndef FTOTVAL_H_
+#define FTOTVAL_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -58,6 +58,12 @@
   /*    This section contains the declaration of functions to validate     */
   /*    some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).         */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_OpenType_Validate                                               */
+  /*    FT_OpenType_Free                                                   */
+  /*                                                                       */
+  /*    FT_VALIDATE_OTXXX                                                  */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -100,14 +106,12 @@
 #define FT_VALIDATE_JSTF  0x1000
 #define FT_VALIDATE_MATH  0x2000
 
-#define FT_VALIDATE_OT  FT_VALIDATE_BASE | \
-                        FT_VALIDATE_GDEF | \
-                        FT_VALIDATE_GPOS | \
-                        FT_VALIDATE_GSUB | \
-                        FT_VALIDATE_JSTF | \
-                        FT_VALIDATE_MATH
-
-  /* */
+#define FT_VALIDATE_OT  ( FT_VALIDATE_BASE | \
+                          FT_VALIDATE_GDEF | \
+                          FT_VALIDATE_GPOS | \
+                          FT_VALIDATE_GSUB | \
+                          FT_VALIDATE_JSTF | \
+                          FT_VALIDATE_MATH )
 
  /**********************************************************************
   *
@@ -165,8 +169,6 @@
                         FT_Bytes  *GSUB_table,
                         FT_Bytes  *JSTF_table );
 
-  /* */
-
  /**********************************************************************
   *
   * @function:
@@ -191,13 +193,12 @@
   FT_OpenType_Free( FT_Face   face,
                     FT_Bytes  table );
 
-
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTOTVAL_H__ */
+#endif /* FTOTVAL_H_ */
 
 
 /* END */
diff --git a/include/ftoutln.h b/include/freetype/ftoutln.h
similarity index 95%
rename from include/ftoutln.h
rename to include/freetype/ftoutln.h
index 6c6d3f9..ef66d48 100644
--- a/include/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
 /*    Support for the FT_Outline type used to store glyph shapes of        */
 /*    most scalable font formats (specification).                          */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005-2014 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTOUTLN_H__
-#define __FTOUTLN_H__
+#ifndef FTOUTLN_H_
+#define FTOUTLN_H_
 
 
 #include <ft2build.h>
@@ -52,7 +52,6 @@
   /*                                                                       */
   /* <Order>                                                               */
   /*    FT_Outline                                                         */
-  /*    FT_OUTLINE_FLAGS                                                   */
   /*    FT_Outline_New                                                     */
   /*    FT_Outline_Done                                                    */
   /*    FT_Outline_Copy                                                    */
@@ -68,13 +67,17 @@
   /*                                                                       */
   /*    FT_Outline_Get_Bitmap                                              */
   /*    FT_Outline_Render                                                  */
-  /*                                                                       */
   /*    FT_Outline_Decompose                                               */
   /*    FT_Outline_Funcs                                                   */
-  /*    FT_Outline_MoveTo_Func                                             */
-  /*    FT_Outline_LineTo_Func                                             */
-  /*    FT_Outline_ConicTo_Func                                            */
-  /*    FT_Outline_CubicTo_Func                                            */
+  /*    FT_Outline_MoveToFunc                                              */
+  /*    FT_Outline_LineToFunc                                              */
+  /*    FT_Outline_ConicToFunc                                             */
+  /*    FT_Outline_CubicToFunc                                             */
+  /*                                                                       */
+  /*    FT_Orientation                                                     */
+  /*    FT_Outline_Get_Orientation                                         */
+  /*                                                                       */
+  /*    FT_OUTLINE_XXX                                                     */
   /*                                                                       */
   /*************************************************************************/
 
@@ -112,6 +115,10 @@
   /*    outline for stroking purposes (otherwise it would result in a      */
   /*    visible dot when round caps are used).                             */
   /*                                                                       */
+  /*    Similarly, the function returns success for an empty outline also  */
+  /*    (doing nothing, this is, not calling any emitter); if necessary,   */
+  /*    you should filter this out, too.                                   */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Outline_Decompose( FT_Outline*              outline,
                         const FT_Outline_Funcs*  func_interface,
@@ -210,6 +217,10 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    An empty outline, or an outline with a single point only is also   */
+  /*    valid.                                                             */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Outline_Check( FT_Outline*  outline );
 
@@ -351,8 +362,8 @@
   /*                                                                       */
   /*    {                                                                  */
   /*      FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );                   */
-  /*      if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE )             */
-  /*        FT_Outline_Embolden( &face->slot->outline, strength );         */
+  /*      if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )            */
+  /*        FT_Outline_Embolden( &face->glyph->outline, strength );        */
   /*    }                                                                  */
   /*                                                                       */
   /*    To get meaningful results, font scaling values must be set with    */
@@ -535,7 +546,7 @@
   *
   * @description:
   *   This function analyzes a glyph outline and tries to compute its
-  *   fill orientation (see @FT_Orientation).  This is done by integrating 
+  *   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
@@ -555,13 +566,12 @@
   FT_EXPORT( FT_Orientation )
   FT_Outline_Get_Orientation( FT_Outline*  outline );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTOUTLN_H__ */
+#endif /* FTOUTLN_H_ */
 
 
 /* END */
diff --git a/include/ftpfr.h b/include/freetype/ftpfr.h
similarity index 97%
rename from include/ftpfr.h
rename to include/freetype/ftpfr.h
index 0b7b7d4..2e1bff2 100644
--- a/include/ftpfr.h
+++ b/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for accessing PFR-specific data (specification only).   */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2006, 2008, 2009 by                        */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTPFR_H__
-#define __FTPFR_H__
+#ifndef FTPFR_H_
+#define FTPFR_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -161,12 +161,12 @@
                       FT_UInt   gindex,
                       FT_Pos   *aadvance );
 
- /* */
+  /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTPFR_H__ */
+#endif /* FTPFR_H_ */
 
 
 /* END */
diff --git a/include/ftrender.h b/include/freetype/ftrender.h
similarity index 93%
rename from include/ftrender.h
rename to include/freetype/ftrender.h
index dd0229b..9f7ed9e 100644
--- a/include/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType renderer modules public interface (specification).          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2005, 2006, 2010 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTRENDER_H__
-#define __FTRENDER_H__
+#ifndef FTRENDER_H_
+#define FTRENDER_H_
 
 
 #include <ft2build.h>
@@ -212,13 +212,8 @@
   /*                                                                       */
   /*    This doesn't change the current renderer for other formats.        */
   /*                                                                       */
-  /*    Currently, only the B/W renderer, if compiled with                 */
-  /*    FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels               */
-  /*    anti-aliasing mode; this option must be set directly in            */
-  /*    `ftraster.c' and is undefined by default) accepts a single tag     */
-  /*    `pal5' to set its gray palette as a character string with          */
-  /*    5~elements.  Consequently, the third and fourth argument are zero  */
-  /*    normally.                                                          */
+  /*    Currently, no FreeType renderer module uses `parameters'; you      */
+  /*    should thus always pass NULL as the value.                         */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_Renderer( FT_Library     library,
@@ -226,13 +221,12 @@
                    FT_UInt        num_params,
                    FT_Parameter*  parameters );
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTRENDER_H__ */
+#endif /* FTRENDER_H_ */
 
 
 /* END */
diff --git a/include/ftsizes.h b/include/freetype/ftsizes.h
similarity index 98%
rename from include/ftsizes.h
rename to include/freetype/ftsizes.h
index 4167045..55e0d5c 100644
--- a/include/ftsizes.h
+++ b/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType size objects management (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2006, 2009, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,8 +25,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTSIZES_H__
-#define __FTSIZES_H__
+#ifndef FTSIZES_H_
+#define FTSIZES_H_
 
 
 #include <ft2build.h>
@@ -153,7 +153,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTSIZES_H__ */
+#endif /* FTSIZES_H_ */
 
 
 /* END */
diff --git a/include/ftsnames.h b/include/freetype/ftsnames.h
similarity index 98%
rename from include/ftsnames.h
rename to include/freetype/ftsnames.h
index 88af440..a7b51c2 100644
--- a/include/ftsnames.h
+++ b/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
 /*                                                                         */
 /*    This is _not_ used to retrieve glyph names!                          */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2009, 2010, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,8 +19,8 @@
 /***************************************************************************/
 
 
-#ifndef __FT_SFNT_NAMES_H__
-#define __FT_SFNT_NAMES_H__
+#ifndef FTSNAMES_H_
+#define FTSNAMES_H_
 
 
 #include <ft2build.h>
@@ -194,7 +194,7 @@
 
 FT_END_HEADER
 
-#endif /* __FT_SFNT_NAMES_H__ */
+#endif /* FTSNAMES_H_ */
 
 
 /* END */
diff --git a/include/ftstroke.h b/include/freetype/ftstroke.h
similarity index 95%
rename from include/ftstroke.h
rename to include/freetype/ftstroke.h
index a498e4a..b3b9922 100644
--- a/include/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (specification).                               */
 /*                                                                         */
-/*  Copyright 2002-2006, 2008, 2009, 2011-2012 by                          */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FT_STROKE_H__
-#define __FT_STROKE_H__
+#ifndef FTSTROKE_H_
+#define FTSTROKE_H_
 
 #include <ft2build.h>
 #include FT_OUTLINE_H
@@ -46,6 +46,38 @@
   *    This can be useful to generate `bordered' glyph, i.e., glyphs
   *    displayed with a coloured (and anti-aliased) border around their
   *    shape.
+  *
+  * @order:
+  *    FT_Stroker
+  *
+  *    FT_Stroker_LineJoin
+  *    FT_Stroker_LineCap
+  *    FT_StrokerBorder
+  *
+  *    FT_Outline_GetInsideBorder
+  *    FT_Outline_GetOutsideBorder
+  *
+  *    FT_Glyph_Stroke
+  *    FT_Glyph_StrokeBorder
+  *
+  *    FT_Stroker_New
+  *    FT_Stroker_Set
+  *    FT_Stroker_Rewind
+  *    FT_Stroker_ParseOutline
+  *    FT_Stroker_Done
+  *
+  *    FT_Stroker_BeginSubPath
+  *    FT_Stroker_EndSubPath
+  *
+  *    FT_Stroker_LineTo
+  *    FT_Stroker_ConicTo
+  *    FT_Stroker_CubicTo
+  *
+  *    FT_Stroker_GetBorderCounts
+  *    FT_Stroker_ExportBorder
+  *    FT_Stroker_GetCounts
+  *    FT_Stroker_Export
+  *
   */
 
 
@@ -55,7 +87,7 @@
   *   FT_Stroker
   *
   * @description:
-  *   Opaque handler to a path stroker object.
+  *   Opaque handle to a path stroker object.
   */
   typedef struct FT_StrokerRec_*  FT_Stroker;
 
@@ -276,6 +308,8 @@
    * @note:
    *   The radius is expressed in the same units as the outline
    *   coordinates.
+   *
+   *   This function calls @FT_Stroker_Rewind automatically.
    */
   FT_EXPORT( void )
   FT_Stroker_Set( FT_Stroker           stroker,
@@ -570,10 +604,10 @@
    *   receive all new data.
    *
    *   When an outline, or a sub-path, is `closed', the stroker generates
-   *   two independent `border' outlines, named `left' and `right'
+   *   two independent `border' outlines, named `left' and `right'.
    *
    *   When the outline, or a sub-path, is `opened', the stroker merges
-   *   the `border' outlines with caps. The `left' border receives all
+   *   the `border' outlines with caps.  The `left' border receives all
    *   points, while the `right' border becomes empty.
    *
    *   Use the function @FT_Stroker_Export instead if you want to
@@ -736,11 +770,11 @@
                          FT_Bool      inside,
                          FT_Bool      destroy );
 
- /* */
+  /* */
 
 FT_END_HEADER
 
-#endif /* __FT_STROKE_H__ */
+#endif /* FTSTROKE_H_ */
 
 
 /* END */
diff --git a/include/ftsynth.h b/include/freetype/ftsynth.h
similarity index 89%
rename from include/ftsynth.h
rename to include/freetype/ftsynth.h
index 839ab5e..fdfcb69 100644
--- a/include/ftsynth.h
+++ b/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
 /*    FreeType synthesizing code for emboldening and slanting              */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2006, 2008, 2012, 2013 by                   */
+/*  Copyright 2000-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -41,8 +41,8 @@
   /* adapted to the particular needs.                               */
 
 
-#ifndef __FTSYNTH_H__
-#define __FTSYNTH_H__
+#ifndef FTSYNTH_H_
+#define FTSYNTH_H_
 
 
 #include <ft2build.h>
@@ -62,8 +62,10 @@
   /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden.           */
   /*                                                                       */
   /* For emboldened outlines the height, width, and advance metrics are    */
-  /* increased by the strength of the emboldening.  You can also call      */
-  /* @FT_Outline_Get_CBox to get precise values.                           */
+  /* increased by the strength of the emboldening -- this even affects     */
+  /* mono-width fonts!                                                     */
+  /*                                                                       */
+  /* You can also call @FT_Outline_Get_CBox to get precise values.         */
   FT_EXPORT( void )
   FT_GlyphSlot_Embolden( FT_GlyphSlot  slot );
 
@@ -73,9 +75,10 @@
 
   /* */
 
+
 FT_END_HEADER
 
-#endif /* __FTSYNTH_H__ */
+#endif /* FTSYNTH_H_ */
 
 
 /* END */
diff --git a/include/ftsystem.h b/include/freetype/ftsystem.h
similarity index 94%
rename from include/ftsystem.h
rename to include/freetype/ftsystem.h
index e07460c..a75f958 100644
--- a/include/ftsystem.h
+++ b/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType low-level system interface definition (specification).      */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2005, 2010 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTSYSTEM_H__
-#define __FTSYSTEM_H__
+#ifndef FTSYSTEM_H_
+#define FTSYSTEM_H_
 
 
 #include <ft2build.h>
@@ -192,6 +192,10 @@
    * @description:
    *   A handle to an input stream.
    *
+   * @also:
+   *   See @FT_StreamRec for the publicly accessible fields of a given
+   *   stream object.
+   *
    */
   typedef struct FT_StreamRec_*  FT_Stream;
 
@@ -285,6 +289,11 @@
    *   size ::
    *     The stream size in bytes.
    *
+   *     In case of compressed streams where the size is unknown before
+   *     actually doing the decompression, the value is set to 0x7FFFFFFF.
+   *     (Note that this size value can occur for normal streams also; it is
+   *     thus just a hint.)
+   *
    *   pos ::
    *     The current position within the stream.
    *
@@ -335,13 +344,12 @@
 
   } FT_StreamRec;
 
-
   /* */
 
 
 FT_END_HEADER
 
-#endif /* __FTSYSTEM_H__ */
+#endif /* FTSYSTEM_H_ */
 
 
 /* END */
diff --git a/include/fttrigon.h b/include/freetype/fttrigon.h
similarity index 96%
rename from include/fttrigon.h
rename to include/freetype/fttrigon.h
index 65143cb..f789b52 100644
--- a/include/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (specification).                    */
 /*                                                                         */
-/*  Copyright 2001, 2003, 2005, 2007, 2013 by                              */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTTRIGON_H__
-#define __FTTRIGON_H__
+#ifndef FTTRIGON_H_
+#define FTTRIGON_H_
 
 #include FT_FREETYPE_H
 
@@ -225,8 +225,8 @@
    *
    * @description:
    *   Return the unit vector corresponding to a given angle.  After the
-   *   call, the value of `vec.x' will be `sin(angle)', and the value of
-   *   `vec.y' will be `cos(angle)'.
+   *   call, the value of `vec.x' will be `cos(angle)', and the value of
+   *   `vec.y' will be `sin(angle)'.
    *
    *   This function is useful to retrieve both the sinus and cosinus of a
    *   given angle quickly.
@@ -237,7 +237,7 @@
    *
    * @input:
    *   angle ::
-   *     The address of angle.
+   *     The input angle.
    *
    */
   FT_EXPORT( void )
@@ -259,7 +259,7 @@
    *
    * @input:
    *   angle ::
-   *     The address of angle.
+   *     The input angle.
    *
    */
   FT_EXPORT( void )
@@ -344,7 +344,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTTRIGON_H__ */
+#endif /* FTTRIGON_H_ */
 
 
 /* END */
diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h
new file mode 100644
index 0000000..22186ee
--- /dev/null
+++ b/include/freetype/ftttdrv.h
@@ -0,0 +1,329 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftttdrv.h                                                              */
+/*                                                                         */
+/*    FreeType API for controlling the TrueType driver                     */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  Copyright 2013-2016 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef FTTTDRV_H_
+#define FTTTDRV_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @section:
+   *   tt_driver
+   *
+   * @title:
+   *   The TrueType driver
+   *
+   * @abstract:
+   *   Controlling the TrueType driver module.
+   *
+   * @description:
+   *   While FreeType's TrueType driver doesn't expose API functions by
+   *   itself, it is possible to control its behaviour with @FT_Property_Set
+   *   and @FT_Property_Get.  The following lists the available properties
+   *   together with the necessary macros and structures.
+   *
+   *   The TrueType driver's module name is `truetype'.
+   *
+   *   We start with a list of definitions, kindly provided by Greg
+   *   Hitchcock.
+   *
+   *   _Bi-Level_ _Rendering_
+   *
+   *   Monochromatic rendering, exclusively used in the early days of
+   *   TrueType by both Apple and Microsoft.  Microsoft's GDI interface
+   *   supported hinting of the right-side bearing point, such that the
+   *   advance width could be non-linear.  Most often this was done to
+   *   achieve some level of glyph symmetry.  To enable reasonable
+   *   performance (e.g., not having to run hinting on all glyphs just to
+   *   get the widths) there was a bit in the head table indicating if the
+   *   side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
+   *   cache hinting widths across multiple sizes and device aspect ratios.
+   *
+   *   _Font_ _Smoothing_
+   *
+   *   Microsoft's GDI implementation of anti-aliasing.  Not traditional
+   *   anti-aliasing as the outlines were hinted before the sampling.  The
+   *   widths matched the bi-level rendering.
+   *
+   *   _ClearType_ _Rendering_
+   *
+   *   Technique that uses physical subpixels to improve rendering on LCD
+   *   (and other) displays.  Because of the higher resolution, many methods
+   *   of improving symmetry in glyphs through hinting the right-side
+   *   bearing were no longer necessary.  This lead to what GDI calls
+   *   `natural widths' ClearType, see
+   *   http://www.beatstamm.com/typography/RTRCh4.htm#Sec21.  Since hinting
+   *   has extra resolution, most non-linearity went away, but it is still
+   *   possible for hints to change the advance widths in this mode.
+   *
+   *   _ClearType_ _Compatible_ _Widths_
+   *
+   *   One of the earliest challenges with ClearType was allowing the
+   *   implementation in GDI to be selected without requiring all UI and
+   *   documents to reflow.  To address this, a compatible method of
+   *   rendering ClearType was added where the font hints are executed once
+   *   to determine the width in bi-level rendering, and then re-run in
+   *   ClearType, with the difference in widths being absorbed in the font
+   *   hints for ClearType (mostly in the white space of hints); see
+   *   http://www.beatstamm.com/typography/RTRCh4.htm#Sec20.  Somewhat by
+   *   definition, compatible width ClearType allows for non-linear widths,
+   *   but only when the bi-level version has non-linear widths.
+   *
+   *   _ClearType_ _Subpixel_ _Positioning_
+   *
+   *   One of the nice benefits of ClearType is the ability to more crisply
+   *   display fractional widths; unfortunately, the GDI model of integer
+   *   bitmaps did not support this.  However, the WPF and Direct Write
+   *   frameworks do support fractional widths.  DWrite calls this `natural
+   *   mode', not to be confused with GDI's `natural widths'.  Subpixel
+   *   positioning, in the current implementation of Direct Write,
+   *   unfortunately does not support hinted advance widths, see
+   *   http://www.beatstamm.com/typography/RTRCh4.htm#Sec22.  Note that the
+   *   TrueType interpreter fully allows the advance width to be adjusted in
+   *   this mode, just the DWrite client will ignore those changes.
+   *
+   *   _ClearType_ _Backwards_ _Compatibility_
+   *
+   *   This is a set of exceptions made in the TrueType interpreter to
+   *   minimize hinting techniques that were problematic with the extra
+   *   resolution of ClearType; see
+   *   http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
+   *   http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
+   *   This technique is not to be confused with ClearType compatible
+   *   widths.  ClearType backwards compatibility has no direct impact on
+   *   changing advance widths, but there might be an indirect impact on
+   *   disabling some deltas.  This could be worked around in backwards
+   *   compatibility mode.
+   *
+   *   _Native_ _ClearType_ _Mode_
+   *
+   *   (Not to be confused with `natural widths'.)  This mode removes all
+   *   the exceptions in the TrueType interpreter when running with
+   *   ClearType.  Any issues on widths would still apply, though.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   interpreter-version
+   *
+   * @description:
+
+   *   Currently, three versions are available, two representing the
+   *   bytecode interpreter with subpixel hinting support (old `Infinality'
+   *   code and new stripped-down and higher performance `minimal' code) and
+   *   one without, respectively.  The default is subpixel support if
+   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
+   *   otherwise (since it isn't available then).
+   *
+   *   If subpixel hinting is on, many TrueType bytecode instructions behave
+   *   differently compared to B/W or grayscale rendering (except if `native
+   *   ClearType' is selected by the font).  Microsoft's main idea is to
+   *   render at a much increased horizontal resolution, then sampling down
+   *   the created output to subpixel precision.  However, many older fonts
+   *   are not suited to this and must be specially taken care of by
+   *   applying (hardcoded) tweaks in Microsoft's interpreter.
+   *
+   *   Details on subpixel hinting and some of the necessary tweaks can be
+   *   found in Greg Hitchcock's whitepaper at
+   *   `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'. 
+   *   Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
+   *   or 6x5 supersampling) like discussed in the paper.  Depending on the
+   *   chosen interpreter, it simply ignores instructions on vertical stems
+   *   to arrive at very similar results.
+   *
+   *   The following example code demonstrates how to deactivate subpixel
+   *   hinting (omitting the error handling).
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Face     face;
+   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_35;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "truetype",
+   *                               "interpreter-version",
+   *                               &interpreter_version );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   *   This property can be set via the `FREETYPE_PROPERTIES' environment
+   *   variable (using values `35', `38', or `40').
+   */
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   TT_INTERPRETER_VERSION_XXX
+   *
+   * @description:
+   *   A list of constants used for the @interpreter-version property to
+   *   select the hinting engine for Truetype fonts.
+   *
+   *   The numeric value in the constant names represents the version
+   *   number as returned by the `GETINFO' bytecode instruction.
+   *
+   * @values:
+   *   TT_INTERPRETER_VERSION_35 ::
+   *     Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
+   *     Windows~98; only grayscale and B/W rasterizing is supported.
+   *
+   *   TT_INTERPRETER_VERSION_38 ::
+   *     Version~38 corresponds to MS rasterizer v.1.9; it is roughly
+   *     equivalent to the hinting provided by DirectWrite ClearType (as can
+   *     be found, for example, in the Internet Explorer~9 running on
+   *     Windows~7).  It is used in FreeType to select the `Infinality'
+   *     subpixel hinting code.  The code may be removed in a future
+   *     version.
+   *
+   *   TT_INTERPRETER_VERSION_40 ::
+   *     Version~40 corresponds to MS rasterizer v.2.1; it is roughly
+   *     equivalent to the hinting provided by DirectWrite ClearType (as can
+   *     be found, for example, in Microsoft's Edge Browser on Windows~10). 
+   *     It is used in FreeType to select the `minimal' subpixel hinting
+   *     code, a stripped-down and higher performance version of the
+   *     `Infinality' code.
+   *
+   * @note:
+   *   This property controls the behaviour of the bytecode interpreter
+   *   and thus how outlines get hinted.  It does *not* control how glyph
+   *   get rasterized!  In particular, it does not control subpixel color
+   *   filtering.
+   *
+   *   If FreeType has not been compiled with the configuration option
+   *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
+   *   an `FT_Err_Unimplemented_Feature' error.
+   *
+   *   Depending on the graphics framework, Microsoft uses different
+   *   bytecode and rendering engines.  As a consequence, the version
+   *   numbers returned by a call to the `GETINFO' bytecode instruction are
+   *   more convoluted than desired.
+   *
+   *   Here are two tables that try to shed some light on the possible
+   *   values for the MS rasterizer engine, together with the additional
+   *   features introduced by it.
+   *
+   *   {
+   *     GETINFO framework               version feature
+   *     -------------------------------------------------------------------
+   *         3   GDI (Win 3.1),            v1.0  16-bit, first version
+   *             TrueImage
+   *        33   GDI (Win NT 3.1),         v1.5  32-bit
+   *             HP Laserjet
+   *        34   GDI (Win 95)              v1.6  font smoothing,
+   *                                             new SCANTYPE opcode
+   *        35   GDI (Win 98/2000)         v1.7  (UN)SCALED_COMPONENT_OFFSET
+   *                                               bits in composite glyphs
+   *        36   MGDI (Win CE 2)           v1.6+ classic ClearType
+   *        37   GDI (XP and later),       v1.8  ClearType
+   *             GDI+ old (before Vista)
+   *        38   GDI+ old (Vista, Win 7),  v1.9  subpixel ClearType,
+   *             WPF                             Y-direction ClearType,
+   *                                             additional error checking
+   *        39   DWrite (before Win 8)     v2.0  subpixel ClearType flags
+   *                                               in GETINFO opcode,
+   *                                             bug fixes
+   *        40   GDI+ (after Win 7),       v2.1  Y-direction ClearType flag
+   *             DWrite (Win 8)                    in GETINFO opcode,
+   *                                             Gray ClearType
+   *   }
+   *
+   *   The `version' field gives a rough orientation only, since some
+   *   applications provided certain features much earlier (as an example,
+   *   Microsoft Reader used subpixel and Y-direction ClearType already in
+   *   Windows 2000).  Similarly, updates to a given framework might include
+   *   improved hinting support.
+   *
+   *   {
+   *      version   sampling          rendering        comment
+   *               x        y       x           y
+   *     --------------------------------------------------------------
+   *       v1.0   normal  normal  B/W           B/W    bi-level
+   *       v1.6   high    high    gray          gray   grayscale
+   *       v1.8   high    normal  color-filter  B/W    (GDI) ClearType
+   *       v1.9   high    high    color-filter  gray   Color ClearType
+   *       v2.1   high    normal  gray          B/W    Gray ClearType
+   *       v2.1   high    high    gray          gray   Gray ClearType
+   *   }
+   *
+   *   Color and Gray ClearType are the two available variants of
+   *   `Y-direction ClearType', meaning grayscale rasterization along the
+   *   Y-direction; the name used in the TrueType specification for this
+   *   feature is `symmetric smoothing'.  `Classic ClearType' is the
+   *   original algorithm used before introducing a modified version in
+   *   Win~XP.  Another name for v1.6's grayscale rendering is `font
+   *   smoothing', and `Color ClearType' is sometimes also called `DWrite
+   *   ClearType'.  To differentiate between today's Color ClearType and the
+   *   earlier ClearType variant with B/W rendering along the vertical axis,
+   *   the latter is sometimes called `GDI ClearType'.
+   *
+   *   `Normal' and `high' sampling describe the (virtual) resolution to
+   *   access the rasterized outline after the hinting process.  `Normal'
+   *   means 1 sample per grid line (i.e., B/W).  In the current Microsoft
+   *   implementation, `high' means an extra virtual resolution of 16x16 (or
+   *   16x1) grid lines per pixel for bytecode instructions like `MIRP'.
+   *   After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
+   *   lines for color filtering if Color ClearType is activated.
+   *
+   *   Note that `Gray ClearType' is essentially the same as v1.6's
+   *   grayscale rendering.  However, the GETINFO instruction handles it
+   *   differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1
+   *   returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing),
+   *   and~19 (Gray ClearType).  Also, this mode respects bits 2 and~3 for
+   *   the version~1 gasp table exclusively (like Color ClearType), while
+   *   v1.6 only respects the values of version~0 (bits 0 and~1).
+   *
+   *   Keep in mind that the features of the above interpreter versions
+   *   might not map exactly to FreeType features or behavior because it is
+   *   a fundamentally different library with different internals.
+   *
+   */
+#define TT_INTERPRETER_VERSION_35  35
+#define TT_INTERPRETER_VERSION_38  38
+#define TT_INTERPRETER_VERSION_40  40
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* FTTTDRV_H_ */
+
+
+/* END */
diff --git a/include/fttypes.h b/include/freetype/fttypes.h
similarity index 98%
rename from include/fttypes.h
rename to include/freetype/fttypes.h
index bd944a4..2673e79 100644
--- a/include/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType simple types definitions (specification only).              */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004, 2006-2009, 2012, 2013 by                    */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTTYPES_H__
-#define __FTTYPES_H__
+#ifndef FTTYPES_H_
+#define FTTYPES_H_
 
 
 #include <ft2build.h>
@@ -57,6 +57,8 @@
   /*    FT_UInt16                                                          */
   /*    FT_Int32                                                           */
   /*    FT_UInt32                                                          */
+  /*    FT_Int64                                                           */
+  /*    FT_UInt64                                                          */
   /*    FT_Short                                                           */
   /*    FT_UShort                                                          */
   /*    FT_Long                                                            */
@@ -78,7 +80,9 @@
   /*    FT_F2Dot14                                                         */
   /*    FT_UnitVector                                                      */
   /*    FT_F26Dot6                                                         */
+  /*    FT_Data                                                            */
   /*                                                                       */
+  /*    FT_MAKE_TAG                                                        */
   /*                                                                       */
   /*    FT_Generic                                                         */
   /*    FT_Generic_Finalizer                                               */
@@ -567,9 +571,9 @@
 
   } FT_ListRec;
 
-
   /* */
 
+
 #define FT_IS_EMPTY( list )  ( (list).head == 0 )
 #define FT_BOOL( x )  ( (FT_Bool)( x ) )
 
@@ -592,7 +596,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTTYPES_H__ */
+#endif /* FTTYPES_H_ */
 
 
 /* END */
diff --git a/include/ftwinfnt.h b/include/freetype/ftwinfnt.h
similarity index 97%
rename from include/ftwinfnt.h
rename to include/freetype/ftwinfnt.h
index 0b67351..a1a715b 100644
--- a/include/ftwinfnt.h
+++ b/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for accessing Windows fnt-specific data.                */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2008 by                                          */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTWINFNT_H__
-#define __FTWINFNT_H__
+#ifndef FTWINFNT_H_
+#define FTWINFNT_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -59,7 +59,7 @@
    *   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/public in the MAPPINGS/VENDORS/MICSFT/WINDOWS
+   *   ftp://ftp.unicode.org/Public in the MAPPINGS/VENDORS/MICSFT/WINDOWS
    *   subdirectory.  cp1361 is roughly a superset of
    *   MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
    *
@@ -95,7 +95,7 @@
    *       second default codepage that most international versions of
    *       Windows have.  It is one of the OEM codepages from
    *
-   *         http://www.microsoft.com/globaldev/reference/cphome.mspx,
+   *         https://msdn.microsoft.com/en-us/goglobal/bb964655,
    *
    *       and is used for the `DOS boxes', to support legacy applications.
    *       A German Windows version for example usually uses ANSI codepage
@@ -259,12 +259,12 @@
   FT_Get_WinFNT_Header( FT_Face               face,
                         FT_WinFNT_HeaderRec  *aheader );
 
-
   /* */
 
+
 FT_END_HEADER
 
-#endif /* __FTWINFNT_H__ */
+#endif /* FTWINFNT_H_ */
 
 
 /* END */
diff --git a/include/internal/autohint.h b/include/freetype/internal/autohint.h
similarity index 98%
rename from include/internal/autohint.h
rename to include/freetype/internal/autohint.h
index 545de93..7ef82b8 100644
--- a/include/internal/autohint.h
+++ b/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level `autohint' module-specific interface (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2002, 2007, 2009, 2012 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,8 +24,8 @@
   /*************************************************************************/
 
 
-#ifndef __AUTOHINT_H__
-#define __AUTOHINT_H__
+#ifndef AUTOHINT_H_
+#define AUTOHINT_H_
 
 
   /*************************************************************************/
@@ -238,7 +238,7 @@
 
 FT_END_HEADER
 
-#endif /* __AUTOHINT_H__ */
+#endif /* AUTOHINT_H_ */
 
 
 /* END */
diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
new file mode 100644
index 0000000..8a884f6
--- /dev/null
+++ b/include/freetype/internal/ftcalc.h
@@ -0,0 +1,418 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcalc.h                                                               */
+/*                                                                         */
+/*    Arithmetic computations (specification).                             */
+/*                                                                         */
+/*  Copyright 1996-2016 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 FTCALC_H_
+#define FTCALC_H_
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
+  /* Provide assembler fragments for performance-critical functions. */
+  /* 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 */
+
+  static __inline FT_Int32
+  FT_MulFix_arm( FT_Int32  a,
+                 FT_Int32  b )
+  {
+    FT_Int32  t, t2;
+
+
+    __asm
+    {
+      smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
+      mov   a,  t,  asr #31         /* a   = (hi >> 31) */
+      add   a,  a,  #0x8000         /* a  += 0x8000 */
+      adds  t2, t2, a               /* t2 += a */
+      adc   t,  t,  #0              /* t  += carry */
+      mov   a,  t2, lsr #16         /* a   = t2 >> 16 */
+      orr   a,  a,  t,  lsl #16     /* a  |= t << 16 */
+    }
+    return a;
+  }
+
+#endif /* __CC_ARM || __ARMCC__ */
+
+
+#ifdef __GNUC__
+
+#if defined( __arm__ )                                 && \
+    ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
+    !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+
+#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
+
+  /* documentation is in freetype.h */
+
+  static __inline__ FT_Int32
+  FT_MulFix_arm( FT_Int32  a,
+                 FT_Int32  b )
+  {
+    FT_Int32  t, t2;
+
+
+    __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) */
+#if defined( __clang__ ) && defined( __thumb2__ )
+      "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 */
+      "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
+      : "=r"(a), "=&r"(t2), "=&r"(t)
+      : "r"(a), "r"(b)
+      : "cc" );
+    return a;
+  }
+
+#endif /* __arm__                      && */
+       /* ( __thumb2__ || !__thumb__ ) && */
+       /* !( __CC_ARM || __ARMCC__ )      */
+
+
+#if defined( __i386__ )
+
+#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
+
+  /* documentation is in freetype.h */
+
+  static __inline__ FT_Int32
+  FT_MulFix_i386( FT_Int32  a,
+                  FT_Int32  b )
+  {
+    FT_Int32  result;
+
+
+    __asm__ __volatile__ (
+      "imul  %%edx\n"
+      "movl  %%edx, %%ecx\n"
+      "sarl  $31, %%ecx\n"
+      "addl  $0x8000, %%ecx\n"
+      "addl  %%ecx, %%eax\n"
+      "adcl  $0, %%edx\n"
+      "shrl  $16, %%eax\n"
+      "shll  $16, %%edx\n"
+      "addl  %%edx, %%eax\n"
+      : "=a"(result), "=d"(b)
+      : "a"(a), "d"(b)
+      : "%ecx", "cc" );
+    return result;
+  }
+
+#endif /* i386 */
+
+#endif /* __GNUC__ */
+
+
+#ifdef _MSC_VER /* Visual C++ */
+
+#ifdef _M_IX86
+
+#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
+
+  /* documentation is in freetype.h */
+
+  static __inline FT_Int32
+  FT_MulFix_i386( FT_Int32  a,
+                  FT_Int32  b )
+  {
+    FT_Int32  result;
+
+    __asm
+    {
+      mov eax, a
+      mov edx, b
+      imul edx
+      mov ecx, edx
+      sar ecx, 31
+      add ecx, 8000h
+      add eax, ecx
+      adc edx, 0
+      shr eax, 16
+      shl edx, 16
+      add eax, edx
+      mov result, eax
+    }
+    return result;
+  }
+
+#endif /* _M_IX86 */
+
+#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 */
+
+
+#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
+#ifdef FT_MULFIX_ASSEMBLER
+#define FT_MulFix( a, b )  FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) )
+#endif
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulDiv_No_Round                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation `(a*b)/c'   */
+  /*    (without rounding) with maximum accuracy (it uses a 64-bit         */
+  /*    intermediate integer whenever necessary).                          */
+  /*                                                                       */
+  /*    This function isn't necessarily as fast as some processor specific */
+  /*    operations, but is at least completely portable.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.                                        */
+  /*    c :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/c'.  This function never traps when trying to */
+  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
+  /*    on the signs of `a' and `b'.                                       */
+  /*                                                                       */
+  FT_BASE( FT_Long )
+  FT_MulDiv_No_Round( FT_Long  a,
+                      FT_Long  b,
+                      FT_Long  c );
+
+
+  /*
+   *  A variant of FT_Matrix_Multiply which scales its result afterwards.
+   *  The idea is that both `a' and `b' are scaled by factors of 10 so that
+   *  the values are as precise as possible to get a correct result during
+   *  the 64bit multiplication.  Let `sa' and `sb' be the scaling factors of
+   *  `a' and `b', respectively, then the scaling factor of the result is
+   *  `sa*sb'.
+   */
+  FT_BASE( void )
+  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
+                             FT_Matrix        *b,
+                             FT_Long           scaling );
+
+
+  /*
+   *  A variant of FT_Vector_Transform.  See comments for
+   *  FT_Matrix_Multiply_Scaled.
+   */
+  FT_BASE( void )
+  FT_Vector_Transform_Scaled( FT_Vector*        vector,
+                              const FT_Matrix*  matrix,
+                              FT_Long           scaling );
+
+
+  /*
+   *  This function normalizes a vector and returns its original length.
+   *  The normalized vector is a 16.16 fixed-point unit vector with length
+   *  close to 0x10000.  The accuracy of the returned length is limited to
+   *  16 bits also.  The function utilizes quick inverse square root
+   *  approximation without divisions and square roots relying on Newton's
+   *  iterations instead.
+   */
+  FT_BASE( FT_UInt32 )
+  FT_Vector_NormLen( FT_Vector*  vector );
+
+
+  /*
+   *  Return -1, 0, or +1, depending on the orientation of a given corner.
+   *  We use the Cartesian coordinate system, with positive vertical values
+   *  going upwards.  The function returns +1 if the corner turns to the
+   *  left, -1 to the right, and 0 for undecidable cases.
+   */
+  FT_BASE( FT_Int )
+  ft_corner_orientation( FT_Pos  in_x,
+                         FT_Pos  in_y,
+                         FT_Pos  out_x,
+                         FT_Pos  out_y );
+
+
+  /*
+   *  Return TRUE if a corner is flat or nearly flat.  This is equivalent to
+   *  saying that the corner point is close to its neighbors, or inside an
+   *  ellipse defined by the neighbor focal points to be more precise.
+   */
+  FT_BASE( FT_Int )
+  ft_corner_is_flat( FT_Pos  in_x,
+                     FT_Pos  in_y,
+                     FT_Pos  out_x,
+                     FT_Pos  out_y );
+
+
+  /*
+   *  Return the most significant bit index.
+   */
+
+#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
+#if defined( __GNUC__ )                                          && \
+    ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
+
+#if FT_SIZEOF_INT == 4
+
+#define FT_MSB( x )  ( 31 - __builtin_clz( x ) )
+
+#elif FT_SIZEOF_LONG == 4
+
+#define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )
+
+#endif
+
+#endif /* __GNUC__ */
+#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+#ifndef FT_MSB
+
+  FT_BASE( FT_Int )
+  FT_MSB( FT_UInt32  z );
+
+#endif
+
+
+  /*
+   *  Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
+   *  two fixed-point arguments instead.
+   */
+  FT_BASE( FT_Fixed )
+  FT_Hypot( FT_Fixed  x,
+            FT_Fixed  y );
+
+
+#if 0
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_SqrtFixed                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of a 16.16 fixed-point value.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: The value to compute the root for.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `sqrt(x)'.                                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is not very fast.                                    */
+  /*                                                                       */
+  FT_BASE( FT_Int32 )
+  FT_SqrtFixed( FT_Int32  x );
+
+#endif /* 0 */
+
+
+#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
+#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
+#define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
+#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) << 2  )
+#define FLOAT_TO_FIXED( x )    ( (FT_Long)( x * 65536.0 ) )
+#define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )
+
+#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
+                                        : ( -( ( 32 - (x) ) & -64 ) ) )
+
+
+FT_END_HEADER
+
+#endif /* FTCALC_H_ */
+
+
+/* END */
diff --git a/include/internal/ftdebug.h b/include/freetype/internal/ftdebug.h
similarity index 98%
rename from include/internal/ftdebug.h
rename to include/freetype/internal/ftdebug.h
index 58a3916..d110457 100644
--- a/include/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004, 2006-2009, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,8 +21,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTDEBUG_H__
-#define __FTDEBUG_H__
+#ifndef FTDEBUG_H_
+#define FTDEBUG_H_
 
 
 #include <ft2build.h>
@@ -140,7 +140,7 @@
   /*    This function may be useful if you want to control FreeType 2's    */
   /*    debug level in your application.                                   */
   /*                                                                       */
-  FT_BASE( const char * )
+  FT_BASE( const char* )
   FT_Trace_Get_Name( FT_Int  idx );
 
 
@@ -249,7 +249,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTDEBUG_H__ */
+#endif /* FTDEBUG_H_ */
 
 
 /* END */
diff --git a/include/internal/ftdriver.h b/include/freetype/internal/ftdriver.h
similarity index 97%
rename from include/internal/ftdriver.h
rename to include/freetype/internal/ftdriver.h
index 940218e..902f02f 100644
--- a/include/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType font driver interface (specification).                      */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2008, 2011-2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTDRIVER_H__
-#define __FTDRIVER_H__
+#ifndef FTDRIVER_H_
+#define FTDRIVER_H_
 
 
 #include <ft2build.h>
@@ -67,15 +67,6 @@
                        FT_Int32      load_flags );
 
 
-  typedef FT_UInt
-  (*FT_CharMap_CharIndexFunc)( FT_CharMap  charmap,
-                               FT_Long     charcode );
-
-  typedef FT_Long
-  (*FT_CharMap_CharNextFunc)( FT_CharMap  charmap,
-                              FT_Long     charcode );
-
-
   typedef FT_Error
   (*FT_Face_GetKerningFunc)( FT_Face     face,
                              FT_UInt     left_glyph,
@@ -213,7 +204,7 @@
   /*    And when it is no longer needed a `destroy' function needs to be   */
   /*    called to release that allocation.                                 */
   /*                                                                       */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains a   */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains a   */
   /*    mechanism to call these functions for the default modules          */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
@@ -403,7 +394,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTDRIVER_H__ */
+#endif /* FTDRIVER_H_ */
 
 
 /* END */
diff --git a/include/internal/ftgloadr.h b/include/freetype/internal/ftgloadr.h
similarity index 73%
rename from include/internal/ftgloadr.h
rename to include/freetype/internal/ftgloadr.h
index ce4dc6c..bebf5db 100644
--- a/include/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph loader (specification).                           */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2005, 2006 by                                    */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTGLOADR_H__
-#define __FTGLOADR_H__
+#ifndef FTGLOADR_H_
+#define FTGLOADR_H_
 
 
 #include <ft2build.h>
@@ -36,24 +36,6 @@
   /*    The glyph loader is an internal object used to load several glyphs */
   /*    together (for example, in the case of composites).                 */
   /*                                                                       */
-  /* <Note>                                                                */
-  /*    The glyph loader implementation is not part of the high-level API, */
-  /*    hence the forward structure declaration.                           */
-  /*                                                                       */
-  typedef struct FT_GlyphLoaderRec_*  FT_GlyphLoader ;
-
-
-#if 0  /* moved to freetype.h in version 2.2 */
-#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS          1
-#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES      2
-#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID        4
-#define FT_SUBGLYPH_FLAG_SCALE                   8
-#define FT_SUBGLYPH_FLAG_XY_SCALE             0x40
-#define FT_SUBGLYPH_FLAG_2X2                  0x80
-#define FT_SUBGLYPH_FLAG_USE_MY_METRICS      0x200
-#endif
-
-
   typedef struct  FT_SubGlyphRec_
   {
     FT_Int     index;
@@ -89,7 +71,7 @@
 
     void*            other;            /* for possible future extension? */
 
-  } FT_GlyphLoaderRec;
+  } FT_GlyphLoaderRec, *FT_GlyphLoader;
 
 
   /* create new empty glyph loader */
@@ -121,21 +103,25 @@
                               FT_UInt         n_contours );
 
 
-#define FT_GLYPHLOADER_CHECK_P( _loader, _count )                         \
-   ( (_count) == 0 || ((_loader)->base.outline.n_points    +              \
-                       (_loader)->current.outline.n_points +              \
-                       (unsigned long)(_count)) <= (_loader)->max_points )
+#define FT_GLYPHLOADER_CHECK_P( _loader, _count )       \
+  ( (_count) == 0                                    || \
+    ( (FT_UInt)(_loader)->base.outline.n_points    +    \
+      (FT_UInt)(_loader)->current.outline.n_points +    \
+      (FT_UInt)(_count) ) <= (_loader)->max_points   )
 
-#define FT_GLYPHLOADER_CHECK_C( _loader, _count )                          \
-  ( (_count) == 0 || ((_loader)->base.outline.n_contours    +              \
-                      (_loader)->current.outline.n_contours +              \
-                      (unsigned long)(_count)) <= (_loader)->max_contours )
+#define FT_GLYPHLOADER_CHECK_C( _loader, _count )         \
+  ( (_count) == 0                                      || \
+    ( (FT_UInt)(_loader)->base.outline.n_contours    +    \
+      (FT_UInt)(_loader)->current.outline.n_contours +    \
+      (FT_UInt)(_count) ) <= (_loader)->max_contours   )
 
-#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points,_contours )      \
-  ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points )   &&                  \
-      FT_GLYPHLOADER_CHECK_C( _loader, _contours ) )                   \
-    ? 0                                                                \
-    : FT_GlyphLoader_CheckPoints( (_loader), (_points), (_contours) ) )
+#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points, _contours ) \
+  ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points )   &&              \
+      FT_GLYPHLOADER_CHECK_C( _loader, _contours ) )               \
+    ? 0                                                            \
+    : FT_GlyphLoader_CheckPoints( (_loader),                       \
+                                  (FT_UInt)(_points),              \
+                                  (FT_UInt)(_contours) ) )
 
 
   /* check that there is enough space to add `n_subs' sub-glyphs to */
@@ -162,7 +148,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTGLOADR_H__ */
+#endif /* FTGLOADR_H_ */
 
 
 /* END */
diff --git a/include/freetype/internal/fthash.h b/include/freetype/internal/fthash.h
new file mode 100644
index 0000000..f22f9d5
--- /dev/null
+++ b/include/freetype/internal/fthash.h
@@ -0,0 +1,136 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fthash.h                                                               */
+/*                                                                         */
+/*    Hashing functions (specification).                                   */
+/*                                                                         */
+/***************************************************************************/
+
+/*
+ * Copyright 2000 Computing Research Labs, New Mexico State University
+ * Copyright 2001-2015
+ *   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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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.
+ */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50     */
+  /*                                                                       */
+  /*  taken from Mark Leisher's xmbdfed package                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTHASH_H_
+#define FTHASH_H_
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  typedef union  FT_Hashkey_
+  {
+    FT_Int       num;
+    const char*  str;
+
+  } FT_Hashkey;
+
+
+  typedef struct  FT_HashnodeRec_
+  {
+    FT_Hashkey  key;
+    size_t      data;
+
+  } FT_HashnodeRec;
+
+  typedef struct FT_HashnodeRec_  *FT_Hashnode;
+
+
+  typedef FT_ULong
+  (*FT_Hash_LookupFunc)( FT_Hashkey*  key );
+
+  typedef FT_Bool
+  (*FT_Hash_CompareFunc)( FT_Hashkey*  a,
+                          FT_Hashkey*  b );
+
+
+  typedef struct  FT_HashRec_
+  {
+    FT_UInt  limit;
+    FT_UInt  size;
+    FT_UInt  used;
+
+    FT_Hash_LookupFunc   lookup;
+    FT_Hash_CompareFunc  compare;
+
+    FT_Hashnode*  table;
+
+  } FT_HashRec;
+
+  typedef struct FT_HashRec_  *FT_Hash;
+
+
+  FT_Error
+  ft_hash_str_init( FT_Hash    hash,
+                    FT_Memory  memory );
+
+  FT_Error
+  ft_hash_num_init( FT_Hash    hash,
+                    FT_Memory  memory );
+
+  void
+  ft_hash_str_free( FT_Hash    hash,
+                    FT_Memory  memory );
+
+#define ft_hash_num_free  ft_hash_str_free
+
+  FT_Error
+  ft_hash_str_insert( const char*  key,
+                      size_t       data,
+                      FT_Hash      hash,
+                      FT_Memory    memory );
+
+  FT_Error
+  ft_hash_num_insert( FT_Int     num,
+                      size_t     data,
+                      FT_Hash    hash,
+                      FT_Memory  memory );
+
+  size_t*
+  ft_hash_str_lookup( const char*  key,
+                      FT_Hash      hash );
+
+  size_t*
+  ft_hash_num_lookup( FT_Int   num,
+                      FT_Hash  hash );
+
+
+FT_END_HEADER
+
+
+#endif /* FTHASH_H_ */
+
+
+/* END */
diff --git a/include/internal/ftmemory.h b/include/freetype/internal/ftmemory.h
similarity index 91%
rename from include/internal/ftmemory.h
rename to include/freetype/internal/ftmemory.h
index 3d51aee..fc33b2f 100644
--- a/include/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType memory management macros (specification).               */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2007, 2010, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTMEMORY_H__
-#define __FTMEMORY_H__
+#ifndef FTMEMORY_H_
+#define FTMEMORY_H_
 
 
 #include <ft2build.h>
@@ -65,13 +65,15 @@
 
 #ifdef __cplusplus
 
-  extern "C++"
+extern "C++"
+{
   template <typename T> inline T*
   cplusplus_typeof(        T*,
                     void  *v )
   {
     return static_cast <T*> ( v );
   }
+}
 
 #define FT_ASSIGNP( p, val )  (p) = cplusplus_typeof( (p), (val) )
 
@@ -106,10 +108,12 @@
 
   /*
    *  The allocation functions return a pointer, and the error code
-   *  is written to through the `p_error' parameter.  See below for
-   *  for documentation.
+   *  is written to through the `p_error' parameter.
    */
 
+  /* The `q' variants of the functions below (`q' for `quick') don't fill */
+  /* the allocated or reallocated memory with zero bytes.                 */
+
   FT_BASE( FT_Pointer )
   ft_mem_alloc( FT_Memory  memory,
                 FT_Long    size,
@@ -141,6 +145,9 @@
                const void*  P );
 
 
+  /* The `Q' variants of the macros below (`Q' for `quick') don't fill */
+  /* the allocated or reallocated memory with zero bytes.              */
+
 #define FT_MEM_ALLOC( ptr, size )                               \
           FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory,          \
                                                (FT_Long)(size), \
@@ -215,11 +222,14 @@
 #define FT_MEM_SET_ERROR( cond )  ( (cond), error != 0 )
 
 
-#define FT_MEM_SET( dest, byte, count )     ft_memset( dest, byte, count )
+#define FT_MEM_SET( dest, byte, count )               \
+          ft_memset( dest, byte, (FT_Offset)(count) )
 
-#define FT_MEM_COPY( dest, source, count )  ft_memcpy( dest, source, count )
+#define FT_MEM_COPY( dest, source, count )              \
+          ft_memcpy( dest, source, (FT_Offset)(count) )
 
-#define FT_MEM_MOVE( dest, source, count )  ft_memmove( dest, source, count )
+#define FT_MEM_MOVE( dest, source, count )               \
+          ft_memmove( dest, source, (FT_Offset)(count) )
 
 
 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
@@ -227,14 +237,19 @@
 #define FT_ZERO( p )                FT_MEM_ZERO( p, sizeof ( *(p) ) )
 
 
-#define FT_ARRAY_ZERO( dest, count )                        \
-          FT_MEM_ZERO( dest, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_ZERO( dest, count )                             \
+          FT_MEM_ZERO( dest,                                     \
+                       (FT_Offset)(count) * sizeof ( *(dest) ) )
 
-#define FT_ARRAY_COPY( dest, source, count )                        \
-          FT_MEM_COPY( dest, source, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_COPY( dest, source, count )                     \
+          FT_MEM_COPY( dest,                                     \
+                       source,                                   \
+                       (FT_Offset)(count) * sizeof ( *(dest) ) )
 
-#define FT_ARRAY_MOVE( dest, source, count )                        \
-          FT_MEM_MOVE( dest, source, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_MOVE( dest, source, count )                     \
+          FT_MEM_MOVE( dest,                                     \
+                       source,                                   \
+                       (FT_Offset)(count) * sizeof ( *(dest) ) )
 
 
   /*
@@ -372,7 +387,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTMEMORY_H__ */
+#endif /* FTMEMORY_H_ */
 
 
 /* END */
diff --git a/include/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
similarity index 96%
rename from include/internal/ftobjs.h
rename to include/freetype/internal/ftobjs.h
index faa37f8..0a9f2d4 100644
--- a/include/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2006, 2008, 2010, 2012-2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,8 +23,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTOBJS_H__
-#define __FTOBJS_H__
+#ifndef FTOBJS_H_
+#define FTOBJS_H_
 
 #include <ft2build.h>
 #include FT_RENDER_H
@@ -72,12 +72,23 @@
 
 #define FT_ABS( a )     ( (a) < 0 ? -(a) : (a) )
 
+  /*
+   *  Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+   *  algorithm.  We use alpha = 1, beta = 3/8, giving us results with a
+   *  largest error less than 7% compared to the exact value.
+   */
+#define FT_HYPOT( x, y )                 \
+          ( x = FT_ABS( x ),             \
+            y = FT_ABS( y ),             \
+            x > y ? x + ( 3 * y >> 3 )   \
+                  : y + ( 3 * x >> 3 ) )
 
-#define FT_PAD_FLOOR( x, n )  ( (x) & ~((n)-1) )
+  /* we use FT_TYPEOF to suppress signedness compilation warnings */
+#define FT_PAD_FLOOR( x, n )  ( (x) & ~FT_TYPEOF( x )( (n)-1 ) )
 #define FT_PAD_ROUND( x, n )  FT_PAD_FLOOR( (x) + ((n)/2), n )
 #define FT_PAD_CEIL( x, n )   FT_PAD_FLOOR( (x) + ((n)-1), n )
 
-#define FT_PIX_FLOOR( x )     ( (x) & ~63 )
+#define FT_PIX_FLOOR( x )     ( (x) & ~FT_TYPEOF( x )63 )
 #define FT_PIX_ROUND( x )     FT_PIX_FLOOR( (x) + 32 )
 #define FT_PIX_CEIL( x )      FT_PIX_FLOOR( (x) + 63 )
 
@@ -330,12 +341,6 @@
   /*      this data when first opened.  This field exists only if          */
   /*      @FT_CONFIG_OPTION_INCREMENTAL is defined.                        */
   /*                                                                       */
-  /*    ignore_unpatented_hinter ::                                        */
-  /*      This boolean flag instructs the glyph loader to ignore the       */
-  /*      native font hinter, if one is found.  This is exclusively used   */
-  /*      in the case when the unpatented hinter is compiled within the    */
-  /*      library.                                                         */
-  /*                                                                       */
   /*    refcount ::                                                        */
   /*      A counter initialized to~1 at the time an @FT_Face structure is  */
   /*      created.  @FT_Reference_Face increments this counter, and        */
@@ -354,7 +359,6 @@
     FT_Incremental_InterfaceRec*  incremental_interface;
 #endif
 
-    FT_Bool             ignore_unpatented_hinter;
     FT_Int              refcount;
 
   } FT_Face_InternalRec;
@@ -394,7 +398,7 @@
   /*    glyph_hints       :: Format-specific glyph hints management.       */
   /*                                                                       */
 
-#define FT_GLYPH_OWN_BITMAP  0x1
+#define FT_GLYPH_OWN_BITMAP  0x1U
 
   typedef struct  FT_Slot_InternalRec_
   {
@@ -495,6 +499,9 @@
 #define FT_DRIVER_HAS_HINTER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
                                      FT_MODULE_DRIVER_HAS_HINTER )
 
+#define FT_DRIVER_HINTS_LIGHTLY( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                        FT_MODULE_DRIVER_HINTS_LIGHTLY )
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -525,6 +532,14 @@
   ft_module_get_service( FT_Module    module,
                          const char*  service_id );
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+  FT_BASE( FT_Error )
+  ft_property_string_set( FT_Library        library,
+                          const FT_String*  module_name,
+                          const FT_String*  property_name,
+                          FT_String*        value );
+#endif
+
   /* */
 
 
@@ -603,12 +618,12 @@
 
 #define FT_REQUEST_WIDTH( req )                                            \
           ( (req)->horiResolution                                          \
-              ? (FT_Pos)( (req)->width * (req)->horiResolution + 36 ) / 72 \
+              ? ( (req)->width * (FT_Pos)(req)->horiResolution + 36 ) / 72 \
               : (req)->width )
 
 #define FT_REQUEST_HEIGHT( req )                                            \
           ( (req)->vertResolution                                           \
-              ? (FT_Pos)( (req)->height * (req)->vertResolution + 36 ) / 72 \
+              ? ( (req)->height * (FT_Pos)(req)->vertResolution + 36 ) / 72 \
               : (req)->height )
 
 
@@ -730,9 +745,8 @@
   /*     faces_list   :: The list of faces currently opened by this        */
   /*                     driver.                                           */
   /*                                                                       */
-  /*     glyph_loader :: The glyph loader for all faces managed by this    */
-  /*                     driver.  This object isn't defined for unscalable */
-  /*                     formats.                                          */
+  /*     glyph_loader :: Unused.  Used to be glyph loader for all faces    */
+  /*                     managed by this driver.                           */
   /*                                                                       */
   typedef struct  FT_DriverRec_
   {
@@ -762,13 +776,6 @@
 #define FT_DEBUG_HOOK_TRUETYPE            0
 
 
-  /* Set this debug hook to a non-null pointer to force unpatented hinting */
-  /* for all faces when both TT_USE_BYTECODE_INTERPRETER and               */
-  /* TT_CONFIG_OPTION_UNPATENTED_HINTING are defined.  This is only used   */
-  /* during debugging.                                                     */
-#define FT_DEBUG_HOOK_UNPATENTED_HINTING  1
-
-
   typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
                                             FT_Render_Mode  render_mode,
                                             FT_Library      library );
@@ -834,7 +841,7 @@
   /*                        filtering callback function.                   */
   /*                                                                       */
   /*    pic_container    :: Contains global structs and tables, instead    */
-  /*                        of defining them globallly.                    */
+  /*                        of defining them globally.                     */
   /*                                                                       */
   /*    refcount         :: A counter initialized to~1 at the time an      */
   /*                        @FT_Library structure is created.              */
@@ -972,8 +979,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Outline_Funcs struct.         */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated structure to be filled.             */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1031,8 +1038,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Raster_Funcs struct.          */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated structure to be filled.             */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1091,8 +1098,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Glyph_Class struct.           */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated stcture to be filled.               */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1165,11 +1172,11 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Renderer_Class struct.        */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion will need  */
-  /*    to be called with a pointer where the allocated structure is       */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' function will      */
+  /*    need to be called with a pointer where the allocated structure is  */
   /*    returned.  And when it is no longer needed a `destroy' function    */
   /*    needs to be called to release that allocation.                     */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
@@ -1369,11 +1376,11 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of an FT_Module_Class struct.       */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion needs to   */
-  /*    be called with a pointer where the allocated structure is          */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' function needs     */
+  /*    to be called with a pointer where the allocated structure is       */
   /*    returned.  And when it is no longer needed a `destroy' function    */
   /*    needs to be called to release that allocation.                     */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
@@ -1555,7 +1562,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTOBJS_H__ */
+#endif /* FTOBJS_H_ */
 
 
 /* END */
diff --git a/include/internal/ftpic.h b/include/freetype/internal/ftpic.h
similarity index 94%
rename from include/internal/ftpic.h
rename to include/freetype/internal/ftpic.h
index 485ce7a..6d800a0 100644
--- a/include/internal/ftpic.h
+++ b/include/freetype/internal/ftpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services (declaration).       */
 /*                                                                         */
-/*  Copyright 2009, 2012 by                                                */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,8 +23,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTPIC_H__
-#define __FTPIC_H__
+#ifndef FTPIC_H_
+#define FTPIC_H_
 
 
 FT_BEGIN_HEADER
@@ -65,7 +65,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTPIC_H__ */
+#endif /* FTPIC_H_ */
 
 
 /* END */
diff --git a/include/internal/ftrfork.h b/include/freetype/internal/ftrfork.h
similarity index 97%
rename from include/internal/ftrfork.h
rename to include/freetype/internal/ftrfork.h
index d750cbe..b923401 100644
--- a/include/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (specification).                    */
 /*                                                                         */
-/*  Copyright 2004, 2006, 2007, 2012, 2013 by                              */
+/*  Copyright 2004-2016 by                                                 */
 /*  Masatake YAMATO and Redhat K.K.                                        */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,8 +21,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTRFORK_H__
-#define __FTRFORK_H__
+#ifndef FTRFORK_H_
+#define FTRFORK_H_
 
 
 #include <ft2build.h>
@@ -44,7 +44,7 @@
   typedef struct  FT_RFork_Ref_
   {
     FT_UShort  res_id;
-    FT_ULong   offset;
+    FT_Long    offset;
 
   } FT_RFork_Ref;
 
@@ -83,7 +83,7 @@
 
   /* this array is a storage in non-PIC mode, so ; is needed in END */
 #define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type )  \
-          const type name[] = {
+          static const type name[] = {
 #define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix )  \
           { raccess_guess_ ## func_suffix,                           \
             FT_RFork_Rule_ ## type_suffix },
@@ -227,7 +227,7 @@
   /*    sort_by_res_id ::                                                  */
   /*      A Boolean to sort the fragmented resource by their ids.          */
   /*      The fragmented resources for `POST' resource should be sorted    */
-  /*      to restore Type1 font properly.  For `snft' resources, sorting   */
+  /*      to restore Type1 font properly.  For `sfnt' resources, sorting   */
   /*      may induce a different order of the faces in comparison to that  */
   /*      by QuickDraw API.                                                */
   /*                                                                       */
@@ -260,7 +260,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTRFORK_H__ */
+#endif /* FTRFORK_H_ */
 
 
 /* END */
diff --git a/include/internal/ftserv.h b/include/freetype/internal/ftserv.h
similarity index 96%
rename from include/internal/ftserv.h
rename to include/freetype/internal/ftserv.h
index 1203ec8..9189717 100644
--- a/include/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType services (specification only).                          */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009, 2012, 2013 by                               */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,8 +28,8 @@
   /*************************************************************************/
 
 
-#ifndef __FTSERV_H__
-#define __FTSERV_H__
+#ifndef FTSERV_H_
+#define FTSERV_H_
 
 
 FT_BEGIN_HEADER
@@ -734,30 +734,30 @@
    *  The header files containing the services.
    */
 
-#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>
+#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_FONT_FORMAT_H        <freetype/internal/services/svfntfmt.h>
+#define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
 
  /* */
 
 FT_END_HEADER
 
-#endif /* __FTSERV_H__ */
+#endif /* FTSERV_H_ */
 
 
 /* END */
diff --git a/include/internal/ftstream.h b/include/freetype/internal/ftstream.h
similarity index 98%
rename from include/internal/ftstream.h
rename to include/freetype/internal/ftstream.h
index 2661858..6d04875 100644
--- a/include/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Stream handling (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2006, 2011, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTSTREAM_H__
-#define __FTSTREAM_H__
+#ifndef FTSTREAM_H_
+#define FTSTREAM_H_
 
 
 #include <ft2build.h>
@@ -361,7 +361,7 @@
                   FT_Long    distance );
 
   /* return current stream position */
-  FT_BASE( FT_Long )
+  FT_BASE( FT_ULong )
   FT_Stream_Pos( FT_Stream  stream );
 
   /* read bytes from a stream into a user-allocated buffer, returns an */
@@ -530,7 +530,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTSTREAM_H__ */
+#endif /* FTSTREAM_H_ */
 
 
 /* END */
diff --git a/include/internal/fttrace.h b/include/freetype/internal/fttrace.h
similarity index 98%
rename from include/internal/fttrace.h
rename to include/freetype/internal/fttrace.h
index d5253db..efb3355 100644
--- a/include/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tracing handling (specification only).                               */
 /*                                                                         */
-/*  Copyright 2002, 2004-2007, 2009, 2011-2014 by                          */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -148,7 +148,7 @@
 FT_TRACE_DEF( aflatin )
 FT_TRACE_DEF( aflatin2 )
 FT_TRACE_DEF( afwarp )
-FT_TRACE_DEF( afharfbuzz )
+FT_TRACE_DEF( afshaper )
 FT_TRACE_DEF( afglobal )
 
 /* END */
diff --git a/include/internal/ftvalid.h b/include/freetype/internal/ftvalid.h
similarity index 90%
rename from include/internal/ftvalid.h
rename to include/freetype/internal/ftvalid.h
index 12ad036..aac92c9 100644
--- a/include/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType validation support (specification).                         */
 /*                                                                         */
-/*  Copyright 2004, 2013 by                                                */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTVALID_H__
-#define __FTVALID_H__
+#ifndef FTVALID_H_
+#define FTVALID_H_
 
 #include <ft2build.h>
 #include FT_CONFIG_STANDARD_LIBRARY_H   /* for ft_setjmp and ft_longjmp */
@@ -87,13 +87,13 @@
   /* validator structure */
   typedef struct  FT_ValidatorRec_
   {
+    ft_jmp_buf          jump_buffer; /* used for exception handling      */
+
     const FT_Byte*      base;        /* address of table in memory       */
     const FT_Byte*      limit;       /* `base' + sizeof(table) in memory */
     FT_ValidationLevel  level;       /* validation level                 */
     FT_Error            error;       /* error returned. 0 means success  */
 
-    ft_jmp_buf          jump_buffer; /* used for exception handling      */
-
   } FT_ValidatorRec;
 
 #if defined( _MSC_VER )
@@ -126,36 +126,34 @@
   /* Calls ft_validate_error.  Assumes that the `valid' local variable */
   /* holds a pointer to the current validator object.                  */
   /*                                                                   */
-  /* Use preprocessor prescan to pass FT_ERR_PREFIX.                   */
-  /*                                                                   */
-#define FT_INVALID( _prefix, _error )  FT_INVALID_( _prefix, _error )
-#define FT_INVALID_( _prefix, _error ) \
-          ft_validator_error( valid, _prefix ## _error )
+#define FT_INVALID( _error )  FT_INVALID_( _error )
+#define FT_INVALID_( _error ) \
+          ft_validator_error( valid, FT_THROW( _error ) )
 
   /* called when a broken table is detected */
 #define FT_INVALID_TOO_SHORT \
-          FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+          FT_INVALID( Invalid_Table )
 
   /* called when an invalid offset is detected */
 #define FT_INVALID_OFFSET \
-          FT_INVALID( FT_ERR_PREFIX, Invalid_Offset )
+          FT_INVALID( Invalid_Offset )
 
   /* called when an invalid format/value is detected */
 #define FT_INVALID_FORMAT \
-          FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+          FT_INVALID( Invalid_Table )
 
   /* called when an invalid glyph index is detected */
 #define FT_INVALID_GLYPH_ID \
-          FT_INVALID( FT_ERR_PREFIX, Invalid_Glyph_Index )
+          FT_INVALID( Invalid_Glyph_Index )
 
   /* called when an invalid field value is detected */
 #define FT_INVALID_DATA \
-          FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+          FT_INVALID( Invalid_Table )
 
 
 FT_END_HEADER
 
-#endif /* __FTVALID_H__ */
+#endif /* FTVALID_H_ */
 
 
 /* END */
diff --git a/include/internal/internal.h b/include/freetype/internal/internal.h
similarity index 60%
rename from include/internal/internal.h
rename to include/freetype/internal/internal.h
index e0ddb06..8c3c14c 100644
--- a/include/internal/internal.h
+++ b/include/freetype/internal/internal.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Internal header files (specification only).                          */
 /*                                                                         */
-/*  Copyright 1996-2004, 2013 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,28 +24,28 @@
   /*************************************************************************/
 
 
-#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_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_HASH_H                <freetype/internal/fthash.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      <internal/tttypes.h>
-#define FT_INTERNAL_TYPE1_TYPES_H         <internal/t1types.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      <internal/psaux.h>
-#define FT_INTERNAL_POSTSCRIPT_HINTS_H    <internal/pshints.h>
-#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H  <internal/psglobal.h>
+#define FT_INTERNAL_POSTSCRIPT_AUX_H      <freetype/internal/psaux.h>
+#define FT_INTERNAL_POSTSCRIPT_HINTS_H    <freetype/internal/pshints.h>
 
-#define FT_INTERNAL_AUTOHINT_H            <internal/autohint.h>
+#define FT_INTERNAL_AUTOHINT_H            <freetype/internal/autohint.h>
 
 
 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
diff --git a/include/internal/psaux.h b/include/freetype/internal/psaux.h
similarity index 98%
rename from include/internal/psaux.h
rename to include/freetype/internal/psaux.h
index e903114..15dedfd 100644
--- a/include/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
 /*    Auxiliary functions and data structures related to PostScript fonts  */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006, 2008, 2009, 2012 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,13 +17,14 @@
 /***************************************************************************/
 
 
-#ifndef __PSAUX_H__
-#define __PSAUX_H__
+#ifndef PSAUX_H_
+#define PSAUX_H_
 
 
 #include <ft2build.h>
 #include FT_INTERNAL_OBJECTS_H
 #include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_HASH_H
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
 
@@ -71,10 +72,10 @@
     (*done)( PS_Table  table );
 
     FT_Error
-    (*add)( PS_Table    table,
-            FT_Int      idx,
-            void*       object,
-            FT_PtrDist  length );
+    (*add)( PS_Table  table,
+            FT_Int    idx,
+            void*     object,
+            FT_UInt   length );
 
     void
     (*release)( PS_Table  table );
@@ -122,12 +123,12 @@
     FT_Byte*           block;          /* current memory block           */
     FT_Offset          cursor;         /* current cursor in memory block */
     FT_Offset          capacity;       /* current size of memory block   */
-    FT_Long            init;
+    FT_ULong           init;
 
     FT_Int             max_elems;
     FT_Int             num_elems;
     FT_Byte**          elements;       /* addresses of table elements */
-    FT_PtrDist*        lengths;        /* lengths of table elements   */
+    FT_UInt*           lengths;        /* lengths of table elements   */
 
     FT_Memory          memory;
     PS_Table_FuncsRec  funcs;
@@ -365,7 +366,7 @@
     (*to_bytes)( PS_Parser  parser,
                  FT_Byte*   bytes,
                  FT_Offset  max_bytes,
-                 FT_Long*   pnum_bytes,
+                 FT_ULong*  pnum_bytes,
                  FT_Bool    delimiters );
 
     FT_Int
@@ -675,9 +676,10 @@
     FT_Byte**            glyph_names;
 
     FT_Int               lenIV;        /* internal for sub routine calls */
-    FT_UInt              num_subrs;
+    FT_Int               num_subrs;
     FT_Byte**            subrs;
-    FT_PtrDist*          subrs_len;    /* array of subrs length (optional) */
+    FT_UInt*             subrs_len;    /* array of subrs length (optional) */
+    FT_Hash              subrs_hash;   /* used if `num_subrs' was massaged */
 
     FT_Matrix            font_matrix;
     FT_Vector            font_offset;
@@ -871,7 +873,7 @@
 
 FT_END_HEADER
 
-#endif /* __PSAUX_H__ */
+#endif /* PSAUX_H_ */
 
 
 /* END */
diff --git a/include/internal/pshints.h b/include/freetype/internal/pshints.h
similarity index 98%
rename from include/internal/pshints.h
rename to include/freetype/internal/pshints.h
index 3fb18dc..e60dc9c 100644
--- a/include/internal/pshints.h
+++ b/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
 /*    recorders (specification only).  These are used to support native    */
 /*    T1/T2 hints in the `type1', `cid', and `cff' font drivers.           */
 /*                                                                         */
-/*  Copyright 2001-2003, 2005-2007, 2009, 2012 by                          */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,8 +18,8 @@
 /***************************************************************************/
 
 
-#ifndef __PSHINTS_H__
-#define __PSHINTS_H__
+#ifndef PSHINTS_H_
+#define PSHINTS_H_
 
 
 #include <ft2build.h>
@@ -45,7 +45,7 @@
                           T1_Private*   private_dict,
                           PSH_Globals*  aglobals );
 
-  typedef FT_Error
+  typedef void
   (*PSH_Globals_SetScaleFunc)( PSH_Globals  globals,
                                FT_Fixed     x_scale,
                                FT_Fixed     y_scale,
@@ -465,7 +465,7 @@
   typedef void
   (*T2_Hints_StemsFunc)( T2_Hints   hints,
                          FT_UInt    dimension,
-                         FT_UInt    count,
+                         FT_Int     count,
                          FT_Fixed*  coordinates );
 
 
@@ -716,7 +716,7 @@
 
 FT_END_HEADER
 
-#endif /* __PSHINTS_H__ */
+#endif /* PSHINTS_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svbdf.h b/include/freetype/internal/services/svbdf.h
similarity index 95%
rename from include/internal/services/svbdf.h
rename to include/freetype/internal/services/svbdf.h
index 0974752..c24475f 100644
--- a/include/internal/services/svbdf.h
+++ b/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType BDF services (specification).                           */
 /*                                                                         */
-/*  Copyright 2003, 2009, 2012 by                                          */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVBDF_H__
-#define __SVBDF_H__
+#ifndef SVBDF_H_
+#define SVBDF_H_
 
 #include FT_BDF_H
 #include FT_INTERNAL_SERVICE_H
@@ -76,7 +76,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVBDF_H__ */
+#endif /* SVBDF_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svcid.h b/include/freetype/internal/services/svcid.h
similarity index 94%
rename from include/internal/services/svcid.h
rename to include/freetype/internal/services/svcid.h
index 6be3f93..dbbe604 100644
--- a/include/internal/services/svcid.h
+++ b/include/freetype/internal/services/svcid.h
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    The FreeType CID font services (specification).                      */
 /*                                                                         */
-/*  Copyright 2007, 2009, 2012 by Derek Clegg, Michael Toftdal.            */
+/*  Copyright 2007-2016 by                                                 */
+/*  Derek Clegg and Michael Toftdal.                                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -15,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVCID_H__
-#define __SVCID_H__
+#ifndef SVCID_H_
+#define SVCID_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -83,7 +84,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVCID_H__ */
+#endif /* SVCID_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svxf86nm.h b/include/freetype/internal/services/svfntfmt.h
similarity index 65%
rename from include/internal/services/svxf86nm.h
rename to include/freetype/internal/services/svfntfmt.h
index ca5d884..bd295c9 100644
--- a/include/internal/services/svxf86nm.h
+++ b/include/freetype/internal/services/svfntfmt.h
@@ -1,10 +1,10 @@
 /***************************************************************************/
 /*                                                                         */
-/*  svxf86nm.h                                                             */
+/*  svfntfmt.h                                                             */
 /*                                                                         */
-/*    The FreeType XFree86 services (specification only).                  */
+/*    The FreeType font format service (specification only).               */
 /*                                                                         */
-/*  Copyright 2003 by                                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVXF86NM_H__
-#define __SVXF86NM_H__
+#ifndef SVFNTFMT_H_
+#define SVFNTFMT_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -31,17 +31,17 @@
    *  is a simple constant string pointer.
    */
 
-#define FT_SERVICE_ID_XF86_NAME  "xf86-driver-name"
+#define FT_SERVICE_ID_FONT_FORMAT  "font-format"
 
-#define FT_XF86_FORMAT_TRUETYPE  "TrueType"
-#define FT_XF86_FORMAT_TYPE_1    "Type 1"
-#define FT_XF86_FORMAT_BDF       "BDF"
-#define FT_XF86_FORMAT_PCF       "PCF"
-#define FT_XF86_FORMAT_TYPE_42   "Type 42"
-#define FT_XF86_FORMAT_CID       "CID Type 1"
-#define FT_XF86_FORMAT_CFF       "CFF"
-#define FT_XF86_FORMAT_PFR       "PFR"
-#define FT_XF86_FORMAT_WINFNT    "Windows FNT"
+#define FT_FONT_FORMAT_TRUETYPE  "TrueType"
+#define FT_FONT_FORMAT_TYPE_1    "Type 1"
+#define FT_FONT_FORMAT_BDF       "BDF"
+#define FT_FONT_FORMAT_PCF       "PCF"
+#define FT_FONT_FORMAT_TYPE_42   "Type 42"
+#define FT_FONT_FORMAT_CID       "CID Type 1"
+#define FT_FONT_FORMAT_CFF       "CFF"
+#define FT_FONT_FORMAT_PFR       "PFR"
+#define FT_FONT_FORMAT_WINFNT    "Windows FNT"
 
   /* */
 
@@ -49,7 +49,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVXF86NM_H__ */
+#endif /* SVFNTFMT_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svgldict.h b/include/freetype/internal/services/svgldict.h
similarity index 95%
rename from include/internal/services/svgldict.h
rename to include/freetype/internal/services/svgldict.h
index 1d12534..fff29bc 100644
--- a/include/internal/services/svgldict.h
+++ b/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph dictionary services (specification).              */
 /*                                                                         */
-/*  Copyright 2003, 2009, 2012 by                                          */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVGLDICT_H__
-#define __SVGLDICT_H__
+#ifndef SVGLDICT_H_
+#define SVGLDICT_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -85,4 +85,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVGLDICT_H__ */
+#endif /* SVGLDICT_H_ */
+
+
+/* END */
diff --git a/include/internal/services/svgxval.h b/include/freetype/internal/services/svgxval.h
similarity index 94%
rename from include/internal/services/svgxval.h
rename to include/freetype/internal/services/svgxval.h
index 2cdab50..fb8ffba 100644
--- a/include/internal/services/svgxval.h
+++ b/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating TrueTypeGX/AAT tables (specification).   */
 /*                                                                         */
-/*  Copyright 2004, 2005 by                                                */
+/*  Copyright 2004-2016 by                                                 */
 /*  Masatake YAMATO, Red Hat K.K.,                                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
@@ -25,8 +25,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVGXVAL_H__
-#define __SVGXVAL_H__
+#ifndef SVGXVAL_H_
+#define SVGXVAL_H_
 
 #include FT_GX_VALIDATE_H
 #include FT_INTERNAL_VALIDATE_H
@@ -66,7 +66,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVGXVAL_H__ */
+#endif /* SVGXVAL_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svkern.h b/include/freetype/internal/services/svkern.h
similarity index 92%
rename from include/internal/services/svkern.h
rename to include/freetype/internal/services/svkern.h
index 1488adf..a636f1a 100644
--- a/include/internal/services/svkern.h
+++ b/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType Kerning service (specification).                        */
 /*                                                                         */
-/*  Copyright 2006 by                                                      */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVKERN_H__
-#define __SVKERN_H__
+#ifndef SVKERN_H_
+#define SVKERN_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_TRUETYPE_TABLES_H
@@ -45,7 +45,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVKERN_H__ */
+#endif /* SVKERN_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svmm.h b/include/freetype/internal/services/svmm.h
similarity index 96%
rename from include/internal/services/svmm.h
rename to include/freetype/internal/services/svmm.h
index b08a663..b78a19f 100644
--- a/include/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType Multiple Masters and GX var services (specification).   */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2009, 2012 by                                    */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVMM_H__
-#define __SVMM_H__
+#ifndef SVMM_H_
+#define SVMM_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -107,7 +107,7 @@
 
 FT_END_HEADER
 
-#endif /* __SVMM_H__ */
+#endif /* SVMM_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svotval.h b/include/freetype/internal/services/svotval.h
similarity index 92%
rename from include/internal/services/svotval.h
rename to include/freetype/internal/services/svotval.h
index 970bbd5..bc929d4 100644
--- a/include/internal/services/svotval.h
+++ b/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType OpenType validation service (specification).            */
 /*                                                                         */
-/*  Copyright 2004, 2006 by                                                */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVOTVAL_H__
-#define __SVOTVAL_H__
+#ifndef SVOTVAL_H_
+#define SVOTVAL_H_
 
 #include FT_OPENTYPE_VALIDATE_H
 #include FT_INTERNAL_VALIDATE_H
@@ -49,7 +49,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVOTVAL_H__ */
+#endif /* SVOTVAL_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svpfr.h b/include/freetype/internal/services/svpfr.h
similarity index 94%
rename from include/internal/services/svpfr.h
rename to include/freetype/internal/services/svpfr.h
index 462786f..d0f7c4d 100644
--- a/include/internal/services/svpfr.h
+++ b/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Internal PFR service functions (specification).                      */
 /*                                                                         */
-/*  Copyright 2003, 2006 by                                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVPFR_H__
-#define __SVPFR_H__
+#ifndef SVPFR_H_
+#define SVPFR_H_
 
 #include FT_PFR_H
 #include FT_INTERNAL_SERVICE_H
@@ -60,7 +60,7 @@
 
 FT_END_HEADER
 
-#endif /* __SVPFR_H__ */
+#endif /* SVPFR_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svpostnm.h b/include/freetype/internal/services/svpostnm.h
similarity index 95%
rename from include/internal/services/svpostnm.h
rename to include/freetype/internal/services/svpostnm.h
index a76b4fe..f124380 100644
--- a/include/internal/services/svpostnm.h
+++ b/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType PostScript name services (specification).               */
 /*                                                                         */
-/*  Copyright 2003, 2007, 2009, 2012 by                                    */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVPOSTNM_H__
-#define __SVPOSTNM_H__
+#ifndef SVPOSTNM_H_
+#define SVPOSTNM_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -75,7 +75,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVPOSTNM_H__ */
+#endif /* SVPOSTNM_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svprop.h b/include/freetype/internal/services/svprop.h
similarity index 92%
rename from include/internal/services/svprop.h
rename to include/freetype/internal/services/svprop.h
index 22da0bb..75e6244 100644
--- a/include/internal/services/svprop.h
+++ b/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType property service (specification).                       */
 /*                                                                         */
-/*  Copyright 2012 by                                                      */
+/*  Copyright 2012-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVPROP_H__
-#define __SVPROP_H__
+#ifndef SVPROP_H_
+#define SVPROP_H_
 
 
 FT_BEGIN_HEADER
@@ -29,7 +29,8 @@
   typedef FT_Error
   (*FT_Properties_SetFunc)( FT_Module    module,
                             const char*  property_name,
-                            const void*  value );
+                            const void*  value,
+                            FT_Bool      value_is_string );
 
   typedef FT_Error
   (*FT_Properties_GetFunc)( FT_Module    module,
@@ -75,7 +76,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVPROP_H__ */
+#endif /* SVPROP_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svpscmap.h b/include/freetype/internal/services/svpscmap.h
similarity index 97%
rename from include/internal/services/svpscmap.h
rename to include/freetype/internal/services/svpscmap.h
index 030948e..9acc216 100644
--- a/include/internal/services/svpscmap.h
+++ b/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType PostScript charmap service (specification).             */
 /*                                                                         */
-/*  Copyright 2003, 2006, 2009, 2012 by                                    */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVPSCMAP_H__
-#define __SVPSCMAP_H__
+#ifndef SVPSCMAP_H_
+#define SVPSCMAP_H_
 
 #include FT_INTERNAL_OBJECTS_H
 
@@ -171,7 +171,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVPSCMAP_H__ */
+#endif /* SVPSCMAP_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svpsinfo.h b/include/freetype/internal/services/svpsinfo.h
similarity index 96%
rename from include/internal/services/svpsinfo.h
rename to include/freetype/internal/services/svpsinfo.h
index 4bfb506..f2c8060 100644
--- a/include/internal/services/svpsinfo.h
+++ b/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType PostScript info service (specification).                */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2009, 2011, 2012 by                              */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVPSINFO_H__
-#define __SVPSINFO_H__
+#ifndef SVPSINFO_H_
+#define SVPSINFO_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_INTERNAL_TYPE1_TYPES_H
@@ -105,7 +105,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVPSINFO_H__ */
+#endif /* SVPSINFO_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svsfnt.h b/include/freetype/internal/services/svsfnt.h
similarity index 95%
rename from include/internal/services/svsfnt.h
rename to include/freetype/internal/services/svsfnt.h
index d3835aa..0f38cf1 100644
--- a/include/internal/services/svsfnt.h
+++ b/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType SFNT table loading service (specification).             */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2009, 2012 by                                    */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVSFNT_H__
-#define __SVSFNT_H__
+#ifndef SVSFNT_H_
+#define SVSFNT_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_TRUETYPE_TABLES_H
@@ -97,7 +97,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVSFNT_H__ */
+#endif /* SVSFNT_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svttcmap.h b/include/freetype/internal/services/svttcmap.h
similarity index 89%
rename from include/internal/services/svttcmap.h
rename to include/freetype/internal/services/svttcmap.h
index 4370f4c..772c721 100644
--- a/include/internal/services/svttcmap.h
+++ b/include/freetype/internal/services/svttcmap.h
@@ -4,10 +4,8 @@
 /*                                                                         */
 /*    The FreeType TrueType/sfnt cmap extra information service.           */
 /*                                                                         */
-/*  Copyright 2003 by                                                      */
-/*  Masatake YAMATO, Redhat K.K.                                           */
-/*                                                                         */
-/*  Copyright 2003, 2008, 2009, 2012, 2013 by                              */
+/*  Copyright 2003-2016 by                                                 */
+/*  Masatake YAMATO, Redhat K.K.,                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,8 +19,8 @@
 /* Development of this service is support of
    Information-technology Promotion Agency, Japan. */
 
-#ifndef __SVTTCMAP_H__
-#define __SVTTCMAP_H__
+#ifndef SVTTCMAP_H_
+#define SVTTCMAP_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_TRUETYPE_TABLES_H
@@ -50,11 +48,12 @@
   /*      `ttnameid.h'.                                                    */
   /*                                                                       */
   /*    format ::                                                          */
-  /*      The cmap format.  OpenType 1.5 defines the formats 0 (byte       */
+  /*      The cmap format.  OpenType 1.6 defines the formats 0 (byte       */
   /*      encoding table), 2~(high-byte mapping through table), 4~(segment */
   /*      mapping to delta values), 6~(trimmed table mapping), 8~(mixed    */
   /*      16-bit and 32-bit coverage), 10~(trimmed array), 12~(segmented   */
-  /*      coverage), and 14 (Unicode Variation Sequences).                 */
+  /*      coverage), 13~(last resort font), and 14 (Unicode Variation      */
+  /*      Sequences).                                                      */
   /*                                                                       */
   typedef struct  TT_CMapInfo_
   {
@@ -101,7 +100,7 @@
 
 FT_END_HEADER
 
-#endif /* __SVTTCMAP_H__ */
+#endif /* SVTTCMAP_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svtteng.h b/include/freetype/internal/services/svtteng.h
similarity index 91%
rename from include/internal/services/svtteng.h
rename to include/freetype/internal/services/svtteng.h
index 58e02a6..c55061a 100644
--- a/include/internal/services/svtteng.h
+++ b/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType TrueType engine query service (specification).          */
 /*                                                                         */
-/*  Copyright 2006 by                                                      */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVTTENG_H__
-#define __SVTTENG_H__
+#ifndef SVTTENG_H_
+#define SVTTENG_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_MODULE_H
@@ -47,7 +47,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVTTENG_H__ */
+#endif /* SVTTENG_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svttglyf.h b/include/freetype/internal/services/svttglyf.h
similarity index 91%
rename from include/internal/services/svttglyf.h
rename to include/freetype/internal/services/svttglyf.h
index 369eb84..c33edd4 100644
--- a/include/internal/services/svttglyf.h
+++ b/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    The FreeType TrueType glyph service.                                 */
 /*                                                                         */
-/*  Copyright 2007, 2009, 2012 by David Turner.                            */
+/*  Copyright 2007-2016 by                                                 */
+/*  David Turner.                                                          */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -14,8 +15,8 @@
 /*                                                                         */
 /***************************************************************************/
 
-#ifndef __SVTTGLYF_H__
-#define __SVTTGLYF_H__
+#ifndef SVTTGLYF_H_
+#define SVTTGLYF_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_TRUETYPE_TABLES_H
@@ -62,7 +63,7 @@
 
 FT_END_HEADER
 
-#endif /* __SVTTGLYF_H__ */
+#endif /* SVTTGLYF_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svwinfnt.h b/include/freetype/internal/services/svwinfnt.h
similarity index 91%
rename from include/internal/services/svwinfnt.h
rename to include/freetype/internal/services/svwinfnt.h
index 57f7765..c2f6d4c 100644
--- a/include/internal/services/svwinfnt.h
+++ b/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType Windows FNT/FONT service (specification).               */
 /*                                                                         */
-/*  Copyright 2003 by                                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVWINFNT_H__
-#define __SVWINFNT_H__
+#ifndef SVWINFNT_H_
+#define SVWINFNT_H_
 
 #include FT_INTERNAL_SERVICE_H
 #include FT_WINFONTS_H
@@ -44,7 +44,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVWINFNT_H__ */
+#endif /* SVWINFNT_H_ */
 
 
 /* END */
diff --git a/include/internal/sfnt.h b/include/freetype/internal/sfnt.h
similarity index 92%
rename from include/internal/sfnt.h
rename to include/freetype/internal/sfnt.h
index 6b5e41f..e139315 100644
--- a/include/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level `sfnt' driver interface (specification).                  */
 /*                                                                         */
-/*  Copyright 1996-2006, 2009, 2012-2013 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SFNT_H__
-#define __SFNT_H__
+#ifndef SFNT_H_
+#define SFNT_H_
 
 
 #include <ft2build.h>
@@ -44,7 +44,9 @@
   /*    face       :: A handle to the target face object.                  */
   /*                                                                       */
   /*    face_index :: The index of the TrueType font, if we are opening a  */
-  /*                  collection.                                          */
+  /*                  collection, in bits 0-15.  The numbered instance     */
+  /*                  index~+~1 of a GX (sub)font, if applicable, in bits  */
+  /*                  16-30.                                               */
   /*                                                                       */
   /*    num_params :: The number of additional parameters.                 */
   /*                                                                       */
@@ -87,7 +89,9 @@
   /*    face       :: A handle to the target face object.                  */
   /*                                                                       */
   /*    face_index :: The index of the TrueType font, if we are opening a  */
-  /*                  collection.                                          */
+  /*                  collection, in bits 0-15.  The numbered instance     */
+  /*                  index~+~1 of a GX (sub)font, if applicable, in bits  */
+  /*                  16-30.                                               */
   /*                                                                       */
   /*    num_params :: The number of additional parameters.                 */
   /*                                                                       */
@@ -405,14 +409,18 @@
   /* <Input>                                                               */
   /*    face     :: A handle to the target face object.                    */
   /*                                                                       */
-  /*    stream   :: The input stream.                                      */
-  /*                                                                       */
   /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
+  /*    gindex   :: The glyph index.                                       */
   /*                                                                       */
-  typedef FT_Error
+  /* <Output>                                                              */
+  /*    abearing :: The horizontal (or vertical) bearing.  Set to zero in  */
+  /*                case of error.                                         */
+  /*                                                                       */
+  /*    aadvance :: The horizontal (or vertical) advance.  Set to zero in  */
+  /*                case of error.                                         */
+  /*                                                                       */
+  typedef void
   (*TT_Get_Metrics_Func)( TT_Face     face,
                           FT_Bool     vertical,
                           FT_UInt     gindex,
@@ -423,6 +431,33 @@
   /*************************************************************************/
   /*                                                                       */
   /* <FuncType>                                                            */
+  /*    TT_Get_Name_Func                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    From the `name' table, return a given ENGLISH name record in       */
+  /*    ASCII.                                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    nameid   :: The name id of the name record to return.              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    name     :: The address of an allocated string pointer.  NULL if   */
+  /*                no name is present.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Get_Name_Func)( TT_Face      face,
+                       FT_UShort    nameid,
+                       FT_String**  name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
   /*    TT_Load_Table_Func                                                 */
   /*                                                                       */
   /* <Description>                                                         */
@@ -552,6 +587,8 @@
 
     TT_Get_Metrics_Func          get_metrics;
 
+    TT_Get_Name_Func             get_name;
+
   } SFNT_Interface;
 
 
@@ -590,7 +627,8 @@
           free_eblc_,                    \
           set_sbit_strike_,              \
           load_strike_metrics_,          \
-          get_metrics_ )                 \
+          get_metrics_,                  \
+          get_name_ )                    \
   static const SFNT_Interface  class_ =  \
   {                                      \
     goto_table_,                         \
@@ -622,6 +660,7 @@
     set_sbit_strike_,                    \
     load_strike_metrics_,                \
     get_metrics_,                        \
+    get_name_,                           \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
@@ -659,7 +698,8 @@
           free_eblc_,                                   \
           set_sbit_strike_,                             \
           load_strike_metrics_,                         \
-          get_metrics_ )                                \
+          get_metrics_,                                 \
+          get_name_ )                                   \
   void                                                  \
   FT_Init_Class_ ## class_( FT_Library       library,   \
                             SFNT_Interface*  clazz )    \
@@ -695,13 +735,14 @@
     clazz->set_sbit_strike     = set_sbit_strike_;      \
     clazz->load_strike_metrics = load_strike_metrics_;  \
     clazz->get_metrics         = get_metrics_;          \
+    clazz->get_name            = get_name_;             \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
 FT_END_HEADER
 
-#endif /* __SFNT_H__ */
+#endif /* SFNT_H_ */
 
 
 /* END */
diff --git a/include/internal/t1types.h b/include/freetype/internal/t1types.h
similarity index 95%
rename from include/internal/t1types.h
rename to include/freetype/internal/t1types.h
index e20237c..494c011 100644
--- a/include/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
 /*    Basic Type1/Type2 type definitions and interface (specification      */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006, 2008, 2009, 2011, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,14 +17,15 @@
 /***************************************************************************/
 
 
-#ifndef __T1TYPES_H__
-#define __T1TYPES_H__
+#ifndef T1TYPES_H_
+#define T1TYPES_H_
 
 
 #include <ft2build.h>
 #include FT_TYPE1_TABLES_H
 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
 #include FT_INTERNAL_SERVICE_H
+#include FT_INTERNAL_HASH_H
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
 
@@ -106,12 +107,13 @@
 
     FT_Int           num_subrs;
     FT_Byte**        subrs;
-    FT_PtrDist*      subrs_len;
+    FT_UInt*         subrs_len;
+    FT_Hash          subrs_hash;
 
     FT_Int           num_glyphs;
     FT_String**      glyph_names;       /* array of glyph names       */
     FT_Byte**        charstrings;       /* array of glyph charstrings */
-    FT_PtrDist*      charstrings_len;
+    FT_UInt*         charstrings_len;
 
     FT_Byte          paint_type;
     FT_Byte          font_type;
@@ -127,7 +129,7 @@
 
   typedef struct  CID_SubrsRec_
   {
-    FT_UInt    num_subrs;
+    FT_Int     num_subrs;
     FT_Byte**  code;
 
   } CID_SubrsRec, *CID_Subrs;
@@ -157,10 +159,10 @@
 
   typedef struct  AFM_KernPairRec_
   {
-    FT_Int  index1;
-    FT_Int  index2;
-    FT_Int  x;
-    FT_Int  y;
+    FT_UInt  index1;
+    FT_UInt  index2;
+    FT_Int   x;
+    FT_Int   y;
 
   } AFM_KernPairRec, *AFM_KernPair;
 
@@ -171,9 +173,9 @@
     FT_Fixed       Ascender;
     FT_Fixed       Descender;
     AFM_TrackKern  TrackKerns;   /* free if non-NULL */
-    FT_Int         NumTrackKern;
+    FT_UInt        NumTrackKern;
     AFM_KernPair   KernPairs;    /* free if non-NULL */
-    FT_Int         NumKernPair;
+    FT_UInt        NumKernPair;
 
   } AFM_FontInfoRec, *AFM_FontInfo;
 
@@ -249,7 +251,7 @@
 
 FT_END_HEADER
 
-#endif /* __T1TYPES_H__ */
+#endif /* T1TYPES_H_ */
 
 
 /* END */
diff --git a/include/internal/tttypes.h b/include/freetype/internal/tttypes.h
similarity index 97%
rename from include/internal/tttypes.h
rename to include/freetype/internal/tttypes.h
index ad302b8..1767132 100644
--- a/include/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType type definitions and interface (specification    */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2008, 2012-2013 by                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTTYPES_H__
-#define __TTTYPES_H__
+#ifndef TTTYPES_H_
+#define TTTYPES_H_
 
 
 #include <ft2build.h>
@@ -185,7 +185,7 @@
   /*                                                                       */
   /*    CompLength :: Compressed table length (in bytes).                  */
   /*                                                                       */
-  /*    OrigLength :: Unompressed table length (in bytes).                 */
+  /*    OrigLength :: Uncompressed table length (in bytes).                */
   /*                                                                       */
   /*    CheckSum   :: The table checksum.  This value can be ignored.      */
   /*                                                                       */
@@ -614,8 +614,7 @@
   /*                       in use by other platforms (e.g. Newton).        */
   /*                       For details, please see                         */
   /*                                                                       */
-  /*                         http://fonts.apple.com/                       */
-  /*                                TTRefMan/RM06/Chap6bloc.html           */
+  /*                         https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
   /*                                                                       */
   /*   hori             :: The line metrics for horizontal layouts.        */
   /*                                                                       */
@@ -635,8 +634,7 @@
   /*   flags            :: Is this a vertical or horizontal strike?  For   */
   /*                       details, please see                             */
   /*                                                                       */
-  /*                         http://fonts.apple.com/                       */
-  /*                                TTRefMan/RM06/Chap6bloc.html           */
+  /*                         https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
   /*                                                                       */
   typedef struct  TT_SBit_StrikeRec_
   {
@@ -1113,7 +1111,7 @@
   /*                            This field also contains the associated    */
   /*                            vertical metrics table (`vmtx'), if found. */
   /*                            IMPORTANT: The contents of this field is   */
-  /*                            undefined if the `verticalInfo' field is   */
+  /*                            undefined if the `vertical_info' field is  */
   /*                            unset.                                     */
   /*                                                                       */
   /*    num_names            :: The number of name records within this     */
@@ -1235,9 +1233,6 @@
   /*                            interpreters field is also used to hook    */
   /*                            the debugger in `ttdebug'.                 */
   /*                                                                       */
-  /*    unpatented_hinting   :: If true, use only unpatented methods in    */
-  /*                            the bytecode interpreter.                  */
-  /*                                                                       */
   /*    doblend              :: A boolean which is set if the font should  */
   /*                            be blended (this is for GX var).           */
   /*                                                                       */
@@ -1336,10 +1331,6 @@
     /* used to hook the debugger for the `ttdebug' utility.        */
     TT_Interpreter        interpreter;
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Use unpatented hinting only. */
-    FT_Bool               unpatented_hinting;
-#endif
 
     /***********************************************************************/
     /*                                                                     */
@@ -1380,6 +1371,7 @@
     FT_ULong              sbit_table_size;
     TT_SbitTableType      sbit_table_type;
     FT_UInt               sbit_num_strikes;
+    FT_UInt*              sbit_strike_map;
 
     FT_Byte*              kern_table;
     FT_ULong              kern_table_size;
@@ -1395,12 +1387,18 @@
     FT_ULong              horz_metrics_offset;
     FT_ULong              vert_metrics_offset;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* since 2.4.12 */
     FT_ULong              sph_found_func_flags; /* special functions found */
                                                 /* for this face           */
     FT_Bool               sph_compatibility_mode;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    /* since 2.7 */
+    FT_ULong              ebdt_start;  /* either `CBDT', `EBDT', or `bdat' */
+    FT_ULong              ebdt_size;
+#endif
 
   } TT_FaceRec;
 
@@ -1440,7 +1438,7 @@
   {
     FT_Memory   memory;
     FT_UShort   max_points;
-    FT_UShort   max_contours;
+    FT_Short    max_contours;
     FT_UShort   n_points;    /* number of points in zone    */
     FT_Short    n_contours;  /* number of contours          */
 
@@ -1459,11 +1457,23 @@
   /* handle to execution context */
   typedef struct TT_ExecContextRec_*  TT_ExecContext;
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType size object.                                */
+  /*                                                                       */
+  typedef struct TT_SizeRec_*  TT_Size;
+
+
   /* glyph loader structure */
   typedef struct  TT_LoaderRec_
   {
-    FT_Face          face;
-    FT_Size          size;
+    TT_Face          face;
+    TT_Size          size;
     FT_GlyphSlot     glyph;
     FT_GlyphLoader   gloader;
 
@@ -1505,12 +1515,15 @@
     FT_Byte*         cursor;
     FT_Byte*         limit;
 
+    /* since version 2.6.2 */
+    FT_ListRec       composites;
+
   } TT_LoaderRec;
 
 
 FT_END_HEADER
 
-#endif /* __TTTYPES_H__ */
+#endif /* TTTYPES_H_ */
 
 
 /* END */
diff --git a/include/t1tables.h b/include/freetype/t1tables.h
similarity index 75%
rename from include/t1tables.h
rename to include/freetype/t1tables.h
index a14255e..e272324 100644
--- a/include/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
 /*    Basic Type 1/Type 2 tables definitions and interface (specification  */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006, 2008, 2009, 2011 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __T1TABLES_H__
-#define __T1TABLES_H__
+#ifndef T1TABLES_H_
+#define T1TABLES_H_
 
 
 #include <ft2build.h>
@@ -49,6 +49,26 @@
   /*    This section contains the definition of Type 1-specific tables,    */
   /*    including structures related to other PostScript font formats.     */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    PS_FontInfoRec                                                     */
+  /*    PS_FontInfo                                                        */
+  /*    PS_PrivateRec                                                      */
+  /*    PS_Private                                                         */
+  /*                                                                       */
+  /*    CID_FaceDictRec                                                    */
+  /*    CID_FaceDict                                                       */
+  /*    CID_FaceInfoRec                                                    */
+  /*    CID_FaceInfo                                                       */
+  /*                                                                       */
+  /*    FT_Has_PS_Glyph_Names                                              */
+  /*    FT_Get_PS_Font_Info                                                */
+  /*    FT_Get_PS_Font_Private                                             */
+  /*    FT_Get_PS_Font_Value                                               */
+  /*                                                                       */
+  /*    T1_Blend_Flags                                                     */
+  /*    T1_EncodingType                                                    */
+  /*    PS_Dict_Keys                                                       */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -190,14 +210,30 @@
   /*    given blend dictionary (font info or private).  Used to support    */
   /*    Multiple Masters fonts.                                            */
   /*                                                                       */
+  /* <Values>                                                              */
+  /*    T1_BLEND_UNDERLINE_POSITION ::                                     */
+  /*    T1_BLEND_UNDERLINE_THICKNESS ::                                    */
+  /*    T1_BLEND_ITALIC_ANGLE ::                                           */
+  /*    T1_BLEND_BLUE_VALUES ::                                            */
+  /*    T1_BLEND_OTHER_BLUES ::                                            */
+  /*    T1_BLEND_STANDARD_WIDTH ::                                         */
+  /*    T1_BLEND_STANDARD_HEIGHT ::                                        */
+  /*    T1_BLEND_STEM_SNAP_WIDTHS ::                                       */
+  /*    T1_BLEND_STEM_SNAP_HEIGHTS ::                                      */
+  /*    T1_BLEND_BLUE_SCALE ::                                             */
+  /*    T1_BLEND_BLUE_SHIFT ::                                             */
+  /*    T1_BLEND_FAMILY_BLUES ::                                           */
+  /*    T1_BLEND_FAMILY_OTHER_BLUES ::                                     */
+  /*    T1_BLEND_FORCE_BOLD ::                                             */
+  /*                                                                       */
   typedef enum  T1_Blend_Flags_
   {
-    /*# required fields in a FontInfo blend dictionary */
+    /* required fields in a FontInfo blend dictionary */
     T1_BLEND_UNDERLINE_POSITION = 0,
     T1_BLEND_UNDERLINE_THICKNESS,
     T1_BLEND_ITALIC_ANGLE,
 
-    /*# required fields in a Private blend dictionary */
+    /* required fields in a Private blend dictionary */
     T1_BLEND_BLUE_VALUES,
     T1_BLEND_OTHER_BLUES,
     T1_BLEND_STANDARD_WIDTH,
@@ -210,15 +246,13 @@
     T1_BLEND_FAMILY_OTHER_BLUES,
     T1_BLEND_FORCE_BOLD,
 
-    /*# never remove */
-    T1_BLEND_MAX
+    T1_BLEND_MAX    /* do not remove */
 
   } T1_Blend_Flags;
 
-  /* */
 
-
-  /*# backwards compatible definitions */
+  /* these constants are deprecated; use the corresponding */
+  /* `T1_Blend_Flags' values instead                       */
 #define t1_blend_underline_position   T1_BLEND_UNDERLINE_POSITION
 #define t1_blend_underline_thickness  T1_BLEND_UNDERLINE_THICKNESS
 #define t1_blend_italic_angle         T1_BLEND_ITALIC_ANGLE
@@ -235,6 +269,8 @@
 #define t1_blend_force_bold           T1_BLEND_FORCE_BOLD
 #define t1_blend_max                  T1_BLEND_MAX
 
+  /* */
+
 
   /* maximum number of Multiple Masters designs, as defined in the spec */
 #define T1_MAX_MM_DESIGNS     16
@@ -333,10 +369,17 @@
   /*                                                                       */
   typedef struct CID_FaceDictRec_*  CID_FaceDict;
 
-  /* */
 
-
-  /* backwards-compatible definition */
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CID_FontDict                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This type is equivalent to @CID_FaceDictRec.  It is deprecated but */
+  /*    kept to maintain source compatibility between various versions of  */
+  /*    FreeType.                                                          */
+  /*                                                                       */
   typedef CID_FaceDictRec  CID_FontDict;
 
 
@@ -449,8 +492,9 @@
    *    FreeType error code.  0~means success.
    *
    * @note:
-   *    The string pointers within the font info structure are owned by
-   *    the face and don't need to be freed by the caller.
+   *    String pointers within the @PS_FontInfoRec structure are owned by
+   *    the face and don't need to be freed by the caller.  Missing entries
+   *    in the font's FontInfo dictionary are represented by NULL pointers.
    *
    *    If the font's format is not PostScript-based, this function will
    *    return the `FT_Err_Invalid_Argument' error code.
@@ -503,6 +547,13 @@
   /*    An enumeration describing the `Encoding' entry in a Type 1         */
   /*    dictionary.                                                        */
   /*                                                                       */
+  /* <Values>                                                              */
+  /*    T1_ENCODING_TYPE_NONE ::                                           */
+  /*    T1_ENCODING_TYPE_ARRAY ::                                          */
+  /*    T1_ENCODING_TYPE_STANDARD ::                                       */
+  /*    T1_ENCODING_TYPE_ISOLATIN1 ::                                      */
+  /*    T1_ENCODING_TYPE_EXPERT ::                                         */
+  /*                                                                       */
   typedef enum  T1_EncodingType_
   {
     T1_ENCODING_TYPE_NONE = 0,
@@ -523,6 +574,54 @@
   /*    An enumeration used in calls to @FT_Get_PS_Font_Value to identify  */
   /*    the Type~1 dictionary entry to retrieve.                           */
   /*                                                                       */
+  /* <Values>                                                              */
+  /*    PS_DICT_FONT_TYPE ::                                               */
+  /*    PS_DICT_FONT_MATRIX ::                                             */
+  /*    PS_DICT_FONT_BBOX ::                                               */
+  /*    PS_DICT_PAINT_TYPE ::                                              */
+  /*    PS_DICT_FONT_NAME ::                                               */
+  /*    PS_DICT_UNIQUE_ID ::                                               */
+  /*    PS_DICT_NUM_CHAR_STRINGS ::                                        */
+  /*    PS_DICT_CHAR_STRING_KEY ::                                         */
+  /*    PS_DICT_CHAR_STRING ::                                             */
+  /*    PS_DICT_ENCODING_TYPE ::                                           */
+  /*    PS_DICT_ENCODING_ENTRY ::                                          */
+  /*    PS_DICT_NUM_SUBRS ::                                               */
+  /*    PS_DICT_SUBR ::                                                    */
+  /*    PS_DICT_STD_HW ::                                                  */
+  /*    PS_DICT_STD_VW ::                                                  */
+  /*    PS_DICT_NUM_BLUE_VALUES ::                                         */
+  /*    PS_DICT_BLUE_VALUE ::                                              */
+  /*    PS_DICT_BLUE_FUZZ ::                                               */
+  /*    PS_DICT_NUM_OTHER_BLUES ::                                         */
+  /*    PS_DICT_OTHER_BLUE ::                                              */
+  /*    PS_DICT_NUM_FAMILY_BLUES ::                                        */
+  /*    PS_DICT_FAMILY_BLUE ::                                             */
+  /*    PS_DICT_NUM_FAMILY_OTHER_BLUES ::                                  */
+  /*    PS_DICT_FAMILY_OTHER_BLUE ::                                       */
+  /*    PS_DICT_BLUE_SCALE ::                                              */
+  /*    PS_DICT_BLUE_SHIFT ::                                              */
+  /*    PS_DICT_NUM_STEM_SNAP_H ::                                         */
+  /*    PS_DICT_STEM_SNAP_H ::                                             */
+  /*    PS_DICT_NUM_STEM_SNAP_V ::                                         */
+  /*    PS_DICT_STEM_SNAP_V ::                                             */
+  /*    PS_DICT_FORCE_BOLD ::                                              */
+  /*    PS_DICT_RND_STEM_UP ::                                             */
+  /*    PS_DICT_MIN_FEATURE ::                                             */
+  /*    PS_DICT_LEN_IV ::                                                  */
+  /*    PS_DICT_PASSWORD ::                                                */
+  /*    PS_DICT_LANGUAGE_GROUP ::                                          */
+  /*    PS_DICT_VERSION ::                                                 */
+  /*    PS_DICT_NOTICE ::                                                  */
+  /*    PS_DICT_FULL_NAME ::                                               */
+  /*    PS_DICT_FAMILY_NAME ::                                             */
+  /*    PS_DICT_WEIGHT ::                                                  */
+  /*    PS_DICT_IS_FIXED_PITCH ::                                          */
+  /*    PS_DICT_UNDERLINE_POSITION ::                                      */
+  /*    PS_DICT_UNDERLINE_THICKNESS ::                                     */
+  /*    PS_DICT_FS_TYPE ::                                                 */
+  /*    PS_DICT_ITALIC_ANGLE ::                                            */
+  /*                                                                       */
   typedef enum  PS_Dict_Keys_
   {
     /* conventionally in the font dictionary */
@@ -656,7 +755,7 @@
 
 FT_END_HEADER
 
-#endif /* __T1TABLES_H__ */
+#endif /* T1TABLES_H_ */
 
 
 /* END */
diff --git a/include/ttnameid.h b/include/freetype/ttnameid.h
similarity index 87%
rename from include/ttnameid.h
rename to include/freetype/ttnameid.h
index 9711d1d..ce707f1 100644
--- a/include/ttnameid.h
+++ b/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType name ID definitions (specification only).                   */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2008, 2012, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTNAMEID_H__
-#define __TTNAMEID_H__
+#ifndef TTNAMEID_H_
+#define TTNAMEID_H_
 
 
 #include <ft2build.h>
@@ -321,7 +321,7 @@
   /*                                                                       */
   /* The canonical source for the Apple assigned Language ID's is at       */
   /*                                                                       */
-  /*   https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html      */
+  /*   https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html */
   /*                                                                       */
 #define TT_MAC_LANGID_ENGLISH                       0
 #define TT_MAC_LANGID_FRENCH                        1
@@ -470,26 +470,26 @@
 #define TT_MS_LANGID_ARABIC_GENERAL                    0x0001
 #define TT_MS_LANGID_ARABIC_SAUDI_ARABIA               0x0401
 #define TT_MS_LANGID_ARABIC_IRAQ                       0x0801
-#define TT_MS_LANGID_ARABIC_EGYPT                      0x0c01
+#define TT_MS_LANGID_ARABIC_EGYPT                      0x0C01
 #define TT_MS_LANGID_ARABIC_LIBYA                      0x1001
 #define TT_MS_LANGID_ARABIC_ALGERIA                    0x1401
 #define TT_MS_LANGID_ARABIC_MOROCCO                    0x1801
-#define TT_MS_LANGID_ARABIC_TUNISIA                    0x1c01
+#define TT_MS_LANGID_ARABIC_TUNISIA                    0x1C01
 #define TT_MS_LANGID_ARABIC_OMAN                       0x2001
 #define TT_MS_LANGID_ARABIC_YEMEN                      0x2401
 #define TT_MS_LANGID_ARABIC_SYRIA                      0x2801
-#define TT_MS_LANGID_ARABIC_JORDAN                     0x2c01
+#define TT_MS_LANGID_ARABIC_JORDAN                     0x2C01
 #define TT_MS_LANGID_ARABIC_LEBANON                    0x3001
 #define TT_MS_LANGID_ARABIC_KUWAIT                     0x3401
 #define TT_MS_LANGID_ARABIC_UAE                        0x3801
-#define TT_MS_LANGID_ARABIC_BAHRAIN                    0x3c01
+#define TT_MS_LANGID_ARABIC_BAHRAIN                    0x3C01
 #define TT_MS_LANGID_ARABIC_QATAR                      0x4001
 #define TT_MS_LANGID_BULGARIAN_BULGARIA                0x0402
 #define TT_MS_LANGID_CATALAN_SPAIN                     0x0403
 #define TT_MS_LANGID_CHINESE_GENERAL                   0x0004
 #define TT_MS_LANGID_CHINESE_TAIWAN                    0x0404
 #define TT_MS_LANGID_CHINESE_PRC                       0x0804
-#define TT_MS_LANGID_CHINESE_HONG_KONG                 0x0c04
+#define TT_MS_LANGID_CHINESE_HONG_KONG                 0x0C04
 #define TT_MS_LANGID_CHINESE_SINGAPORE                 0x1004
 
 #if 1  /* this looks like the correct value */
@@ -507,7 +507,7 @@
 #define TT_MS_LANGID_DANISH_DENMARK                    0x0406
 #define TT_MS_LANGID_GERMAN_GERMANY                    0x0407
 #define TT_MS_LANGID_GERMAN_SWITZERLAND                0x0807
-#define TT_MS_LANGID_GERMAN_AUSTRIA                    0x0c07
+#define TT_MS_LANGID_GERMAN_AUSTRIA                    0x0C07
 #define TT_MS_LANGID_GERMAN_LUXEMBOURG                 0x1007
 #define TT_MS_LANGID_GERMAN_LIECHTENSTEI               0x1407
 #define TT_MS_LANGID_GREEK_GREECE                      0x0408
@@ -520,69 +520,69 @@
 #define TT_MS_LANGID_ENGLISH_GENERAL                   0x0009
 #define TT_MS_LANGID_ENGLISH_UNITED_STATES             0x0409
 #define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM            0x0809
-#define TT_MS_LANGID_ENGLISH_AUSTRALIA                 0x0c09
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA                 0x0C09
 #define TT_MS_LANGID_ENGLISH_CANADA                    0x1009
 #define TT_MS_LANGID_ENGLISH_NEW_ZEALAND               0x1409
 #define TT_MS_LANGID_ENGLISH_IRELAND                   0x1809
-#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              0x1c09
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              0x1C09
 #define TT_MS_LANGID_ENGLISH_JAMAICA                   0x2009
 #define TT_MS_LANGID_ENGLISH_CARIBBEAN                 0x2409
 #define TT_MS_LANGID_ENGLISH_BELIZE                    0x2809
-#define TT_MS_LANGID_ENGLISH_TRINIDAD                  0x2c09
+#define TT_MS_LANGID_ENGLISH_TRINIDAD                  0x2C09
 #define TT_MS_LANGID_ENGLISH_ZIMBABWE                  0x3009
 #define TT_MS_LANGID_ENGLISH_PHILIPPINES               0x3409
 #define TT_MS_LANGID_ENGLISH_INDONESIA                 0x3809
-#define TT_MS_LANGID_ENGLISH_HONG_KONG                 0x3c09
+#define TT_MS_LANGID_ENGLISH_HONG_KONG                 0x3C09
 #define TT_MS_LANGID_ENGLISH_INDIA                     0x4009
 #define TT_MS_LANGID_ENGLISH_MALAYSIA                  0x4409
 #define TT_MS_LANGID_ENGLISH_SINGAPORE                 0x4809
-#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    0x040a
-#define TT_MS_LANGID_SPANISH_MEXICO                    0x080a
-#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT  0x0c0a
-#define TT_MS_LANGID_SPANISH_GUATEMALA                 0x100a
-#define TT_MS_LANGID_SPANISH_COSTA_RICA                0x140a
-#define TT_MS_LANGID_SPANISH_PANAMA                    0x180a
-#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        0x1c0a
-#define TT_MS_LANGID_SPANISH_VENEZUELA                 0x200a
-#define TT_MS_LANGID_SPANISH_COLOMBIA                  0x240a
-#define TT_MS_LANGID_SPANISH_PERU                      0x280a
-#define TT_MS_LANGID_SPANISH_ARGENTINA                 0x2c0a
-#define TT_MS_LANGID_SPANISH_ECUADOR                   0x300a
-#define TT_MS_LANGID_SPANISH_CHILE                     0x340a
-#define TT_MS_LANGID_SPANISH_URUGUAY                   0x380a
-#define TT_MS_LANGID_SPANISH_PARAGUAY                  0x3c0a
-#define TT_MS_LANGID_SPANISH_BOLIVIA                   0x400a
-#define TT_MS_LANGID_SPANISH_EL_SALVADOR               0x440a
-#define TT_MS_LANGID_SPANISH_HONDURAS                  0x480a
-#define TT_MS_LANGID_SPANISH_NICARAGUA                 0x4c0a
-#define TT_MS_LANGID_SPANISH_PUERTO_RICO               0x500a
-#define TT_MS_LANGID_SPANISH_UNITED_STATES             0x540a
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    0x040A
+#define TT_MS_LANGID_SPANISH_MEXICO                    0x080A
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT  0x0C0A
+#define TT_MS_LANGID_SPANISH_GUATEMALA                 0x100A
+#define TT_MS_LANGID_SPANISH_COSTA_RICA                0x140A
+#define TT_MS_LANGID_SPANISH_PANAMA                    0x180A
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        0x1C0A
+#define TT_MS_LANGID_SPANISH_VENEZUELA                 0x200A
+#define TT_MS_LANGID_SPANISH_COLOMBIA                  0x240A
+#define TT_MS_LANGID_SPANISH_PERU                      0x280A
+#define TT_MS_LANGID_SPANISH_ARGENTINA                 0x2C0A
+#define TT_MS_LANGID_SPANISH_ECUADOR                   0x300A
+#define TT_MS_LANGID_SPANISH_CHILE                     0x340A
+#define TT_MS_LANGID_SPANISH_URUGUAY                   0x380A
+#define TT_MS_LANGID_SPANISH_PARAGUAY                  0x3C0A
+#define TT_MS_LANGID_SPANISH_BOLIVIA                   0x400A
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR               0x440A
+#define TT_MS_LANGID_SPANISH_HONDURAS                  0x480A
+#define TT_MS_LANGID_SPANISH_NICARAGUA                 0x4C0A
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO               0x500A
+#define TT_MS_LANGID_SPANISH_UNITED_STATES             0x540A
   /* The following ID blatantly violate MS specs by using a */
   /* sublanguage > 0x1F.                                    */
-#define TT_MS_LANGID_SPANISH_LATIN_AMERICA             0xE40aU
-#define TT_MS_LANGID_FINNISH_FINLAND                   0x040b
-#define TT_MS_LANGID_FRENCH_FRANCE                     0x040c
-#define TT_MS_LANGID_FRENCH_BELGIUM                    0x080c
-#define TT_MS_LANGID_FRENCH_CANADA                     0x0c0c
-#define TT_MS_LANGID_FRENCH_SWITZERLAND                0x100c
-#define TT_MS_LANGID_FRENCH_LUXEMBOURG                 0x140c
-#define TT_MS_LANGID_FRENCH_MONACO                     0x180c
-#define TT_MS_LANGID_FRENCH_WEST_INDIES                0x1c0c
-#define TT_MS_LANGID_FRENCH_REUNION                    0x200c
-#define TT_MS_LANGID_FRENCH_CONGO                      0x240c
+#define TT_MS_LANGID_SPANISH_LATIN_AMERICA             0xE40AU
+#define TT_MS_LANGID_FINNISH_FINLAND                   0x040B
+#define TT_MS_LANGID_FRENCH_FRANCE                     0x040C
+#define TT_MS_LANGID_FRENCH_BELGIUM                    0x080C
+#define TT_MS_LANGID_FRENCH_CANADA                     0x0C0C
+#define TT_MS_LANGID_FRENCH_SWITZERLAND                0x100C
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG                 0x140C
+#define TT_MS_LANGID_FRENCH_MONACO                     0x180C
+#define TT_MS_LANGID_FRENCH_WEST_INDIES                0x1C0C
+#define TT_MS_LANGID_FRENCH_REUNION                    0x200C
+#define TT_MS_LANGID_FRENCH_CONGO                      0x240C
   /* which was formerly: */
 #define TT_MS_LANGID_FRENCH_ZAIRE  TT_MS_LANGID_FRENCH_CONGO
-#define TT_MS_LANGID_FRENCH_SENEGAL                    0x280c
-#define TT_MS_LANGID_FRENCH_CAMEROON                   0x2c0c
-#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE              0x300c
-#define TT_MS_LANGID_FRENCH_MALI                       0x340c
-#define TT_MS_LANGID_FRENCH_MOROCCO                    0x380c
-#define TT_MS_LANGID_FRENCH_HAITI                      0x3c0c
-  /* and another violation of the spec (see 0xE40aU) */
-#define TT_MS_LANGID_FRENCH_NORTH_AFRICA               0xE40cU
-#define TT_MS_LANGID_HEBREW_ISRAEL                     0x040d
-#define TT_MS_LANGID_HUNGARIAN_HUNGARY                 0x040e
-#define TT_MS_LANGID_ICELANDIC_ICELAND                 0x040f
+#define TT_MS_LANGID_FRENCH_SENEGAL                    0x280C
+#define TT_MS_LANGID_FRENCH_CAMEROON                   0x2C0C
+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE              0x300C
+#define TT_MS_LANGID_FRENCH_MALI                       0x340C
+#define TT_MS_LANGID_FRENCH_MOROCCO                    0x380C
+#define TT_MS_LANGID_FRENCH_HAITI                      0x3C0C
+  /* and another violation of the spec (see 0xE40AU) */
+#define TT_MS_LANGID_FRENCH_NORTH_AFRICA               0xE40CU
+#define TT_MS_LANGID_HEBREW_ISRAEL                     0x040D
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY                 0x040E
+#define TT_MS_LANGID_ICELANDIC_ICELAND                 0x040F
 #define TT_MS_LANGID_ITALIAN_ITALY                     0x0410
 #define TT_MS_LANGID_ITALIAN_SWITZERLAND               0x0810
 #define TT_MS_LANGID_JAPANESE_JAPAN                    0x0411
@@ -600,27 +600,27 @@
 #define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA                0x0818
 #define TT_MS_LANGID_RUSSIAN_RUSSIA                    0x0419
 #define TT_MS_LANGID_RUSSIAN_MOLDAVIA                  0x0819
-#define TT_MS_LANGID_CROATIAN_CROATIA                  0x041a
-#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN              0x081a
-#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           0x0c1a
+#define TT_MS_LANGID_CROATIAN_CROATIA                  0x041A
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN              0x081A
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           0x0C1A
 
 #if 0  /* this used to be this value, but it looks like we were wrong */
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x101a
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x101A
 #else  /* current sources say */
-#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA       0x101a
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x141a
+#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA       0x101A
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x141A
        /* and XPsp2 Platform SDK added (2004-07-26) */
        /* Names are shortened to be significant within 40 chars. */
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN         0x181a
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC      0x181a
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN         0x181A
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC      0x181A
 #endif
 
-#define TT_MS_LANGID_SLOVAK_SLOVAKIA                   0x041b
-#define TT_MS_LANGID_ALBANIAN_ALBANIA                  0x041c
-#define TT_MS_LANGID_SWEDISH_SWEDEN                    0x041d
-#define TT_MS_LANGID_SWEDISH_FINLAND                   0x081d
-#define TT_MS_LANGID_THAI_THAILAND                     0x041e
-#define TT_MS_LANGID_TURKISH_TURKEY                    0x041f
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA                   0x041B
+#define TT_MS_LANGID_ALBANIAN_ALBANIA                  0x041C
+#define TT_MS_LANGID_SWEDISH_SWEDEN                    0x041D
+#define TT_MS_LANGID_SWEDISH_FINLAND                   0x081D
+#define TT_MS_LANGID_THAI_THAILAND                     0x041E
+#define TT_MS_LANGID_TURKISH_TURKEY                    0x041F
 #define TT_MS_LANGID_URDU_PAKISTAN                     0x0420
 #define TT_MS_LANGID_URDU_INDIA                        0x0820
 #define TT_MS_LANGID_INDONESIAN_INDONESIA              0x0421
@@ -633,13 +633,13 @@
 #define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA      0x0827
 #define TT_MS_LANGID_TAJIK_TAJIKISTAN                  0x0428
 #define TT_MS_LANGID_FARSI_IRAN                        0x0429
-#define TT_MS_LANGID_VIETNAMESE_VIET_NAM               0x042a
-#define TT_MS_LANGID_ARMENIAN_ARMENIA                  0x042b
-#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            0x042c
-#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         0x082c
-#define TT_MS_LANGID_BASQUE_SPAIN                      0x042d
-#define TT_MS_LANGID_SORBIAN_GERMANY                   0x042e
-#define TT_MS_LANGID_MACEDONIAN_MACEDONIA              0x042f
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM               0x042A
+#define TT_MS_LANGID_ARMENIAN_ARMENIA                  0x042B
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            0x042C
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         0x082C
+#define TT_MS_LANGID_BASQUE_SPAIN                      0x042D
+#define TT_MS_LANGID_SORBIAN_GERMANY                   0x042E
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA              0x042F
 #define TT_MS_LANGID_SUTU_SOUTH_AFRICA                 0x0430
 #define TT_MS_LANGID_TSONGA_SOUTH_AFRICA               0x0431
 #define TT_MS_LANGID_TSWANA_SOUTH_AFRICA               0x0432
@@ -650,32 +650,32 @@
 #define TT_MS_LANGID_GEORGIAN_GEORGIA                  0x0437
 #define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS           0x0438
 #define TT_MS_LANGID_HINDI_INDIA                       0x0439
-#define TT_MS_LANGID_MALTESE_MALTA                     0x043a
+#define TT_MS_LANGID_MALTESE_MALTA                     0x043A
   /* Added by XPsp2 Platform SDK (2004-07-26) */
-#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY              0x043b
-#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN              0x083b
-#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND             0x0C3b
-#define TT_MS_LANGID_SAMI_LULE_NORWAY                  0x103b
-#define TT_MS_LANGID_SAMI_LULE_SWEDEN                  0x143b
-#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY              0x183b
-#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN              0x1C3b
-#define TT_MS_LANGID_SAMI_SKOLT_FINLAND                0x203b
-#define TT_MS_LANGID_SAMI_INARI_FINLAND                0x243b
+#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY              0x043B
+#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN              0x083B
+#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND             0x0C3B
+#define TT_MS_LANGID_SAMI_LULE_NORWAY                  0x103B
+#define TT_MS_LANGID_SAMI_LULE_SWEDEN                  0x143B
+#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY              0x183B
+#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN              0x1C3B
+#define TT_MS_LANGID_SAMI_SKOLT_FINLAND                0x203B
+#define TT_MS_LANGID_SAMI_INARI_FINLAND                0x243B
   /* ... and we also keep our old identifier... */
-#define TT_MS_LANGID_SAAMI_LAPONIA                     0x043b
+#define TT_MS_LANGID_SAAMI_LAPONIA                     0x043B
 
 #if 0 /* this seems to be a previous inversion */
-#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043c
-#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083c
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043C
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083C
 #else
-#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083c
-#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083C
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043C
 #endif
 
-#define TT_MS_LANGID_YIDDISH_GERMANY                   0x043d
-#define TT_MS_LANGID_MALAY_MALAYSIA                    0x043e
-#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083e
-#define TT_MS_LANGID_KAZAK_KAZAKSTAN                   0x043f
+#define TT_MS_LANGID_YIDDISH_GERMANY                   0x043D
+#define TT_MS_LANGID_MALAY_MALAYSIA                    0x043E
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083E
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN                   0x043F
 #define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440
   /* alias declared in Windows 2000 */
 #define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \
@@ -693,12 +693,12 @@
 #define TT_MS_LANGID_GUJARATI_INDIA                    0x0447
 #define TT_MS_LANGID_ORIYA_INDIA                       0x0448
 #define TT_MS_LANGID_TAMIL_INDIA                       0x0449
-#define TT_MS_LANGID_TELUGU_INDIA                      0x044a
-#define TT_MS_LANGID_KANNADA_INDIA                     0x044b
-#define TT_MS_LANGID_MALAYALAM_INDIA                   0x044c
-#define TT_MS_LANGID_ASSAMESE_INDIA                    0x044d
-#define TT_MS_LANGID_MARATHI_INDIA                     0x044e
-#define TT_MS_LANGID_SANSKRIT_INDIA                    0x044f
+#define TT_MS_LANGID_TELUGU_INDIA                      0x044A
+#define TT_MS_LANGID_KANNADA_INDIA                     0x044B
+#define TT_MS_LANGID_MALAYALAM_INDIA                   0x044C
+#define TT_MS_LANGID_ASSAMESE_INDIA                    0x044D
+#define TT_MS_LANGID_MARATHI_INDIA                     0x044E
+#define TT_MS_LANGID_SANSKRIT_INDIA                    0x044F
 #define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450
 #define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN      0x0850
 #define TT_MS_LANGID_TIBETAN_CHINA                     0x0451
@@ -732,13 +732,13 @@
 #define TT_MS_LANGID_SINDHI_INDIA /* Arabic */         0x0459
 #define TT_MS_LANGID_SINDHI_PAKISTAN                   0x0859
   /* Missing a LCID for Sindhi in Devanagari script */
-#define TT_MS_LANGID_SYRIAC_SYRIA                      0x045a
-#define TT_MS_LANGID_SINHALESE_SRI_LANKA               0x045b
-#define TT_MS_LANGID_CHEROKEE_UNITED_STATES            0x045c
-#define TT_MS_LANGID_INUKTITUT_CANADA                  0x045d
-#define TT_MS_LANGID_AMHARIC_ETHIOPIA                  0x045e
-#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */    0x045f
-#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN           0x085f
+#define TT_MS_LANGID_SYRIAC_SYRIA                      0x045A
+#define TT_MS_LANGID_SINHALESE_SRI_LANKA               0x045B
+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES            0x045C
+#define TT_MS_LANGID_INUKTITUT_CANADA                  0x045D
+#define TT_MS_LANGID_AMHARIC_ETHIOPIA                  0x045E
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */    0x045F
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN           0x085F
   /* Missing a LCID for Tifinagh script */
 #define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */    0x0460
   /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */
@@ -758,15 +758,15 @@
 #define TT_MS_LANGID_FULFULDE_NIGERIA                  0x0467
 #define TT_MS_LANGID_HAUSA_NIGERIA                     0x0468
 #define TT_MS_LANGID_IBIBIO_NIGERIA                    0x0469
-#define TT_MS_LANGID_YORUBA_NIGERIA                    0x046a
-#define TT_MS_LANGID_QUECHUA_BOLIVIA                   0x046b
-#define TT_MS_LANGID_QUECHUA_ECUADOR                   0x086b
-#define TT_MS_LANGID_QUECHUA_PERU                      0x0c6b
-#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA               0x046c
+#define TT_MS_LANGID_YORUBA_NIGERIA                    0x046A
+#define TT_MS_LANGID_QUECHUA_BOLIVIA                   0x046B
+#define TT_MS_LANGID_QUECHUA_ECUADOR                   0x086B
+#define TT_MS_LANGID_QUECHUA_PERU                      0x0C6B
+#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA               0x046C
   /* Also spelled by XPsp2 Platform SDK (2004-07-26) */
 #define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \
           TT_MS_LANGID_SEPEDI_SOUTH_AFRICA
-  /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */
+  /* language codes 0x046D, 0x046E and 0x046F are (still) unknown. */
 #define TT_MS_LANGID_IGBO_NIGERIA                      0x0470
 #define TT_MS_LANGID_KANURI_NIGERIA                    0x0471
 #define TT_MS_LANGID_OROMO_ETHIOPIA                    0x0472
@@ -783,12 +783,12 @@
   /*       studying).                                                     */
 #define TT_MS_LANGID_YI_CHINA                          0x0478
 #define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES   0x0479
-  /* language codes from 0x047a to 0x047f are (still) unknown. */
+  /* language codes from 0x047A to 0x047F are (still) unknown. */
 #define TT_MS_LANGID_UIGHUR_CHINA                      0x0480
 #define TT_MS_LANGID_MAORI_NEW_ZEALAND                 0x0481
 
 #if 0  /* not deemed useful for fonts */
-#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE            0x04ff
+#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE            0x04FF
 #endif
 
 
@@ -1231,7 +1231,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTNAMEID_H__ */
+#endif /* TTNAMEID_H_ */
 
 
 /* END */
diff --git a/include/tttables.h b/include/freetype/tttables.h
similarity index 92%
rename from include/tttables.h
rename to include/freetype/tttables.h
index bb49dc0..1c075dc 100644
--- a/include/tttables.h
+++ b/include/freetype/tttables.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType tables definitions and interface                 */
 /*    (specification only).                                                */
 /*                                                                         */
-/*  Copyright 1996-2005, 2008-2013 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTTABLES_H__
-#define __TTTABLES_H__
+#ifndef TTTABLES_H_
+#define TTTABLES_H_
 
 
 #include <ft2build.h>
@@ -48,6 +48,25 @@
   /*    This section contains the definition of TrueType-specific tables   */
   /*    as well as some routines used to access and process them.          */
   /*                                                                       */
+  /* <Order>                                                               */
+  /*    TT_Header                                                          */
+  /*    TT_HoriHeader                                                      */
+  /*    TT_VertHeader                                                      */
+  /*    TT_OS2                                                             */
+  /*    TT_Postscript                                                      */
+  /*    TT_PCLT                                                            */
+  /*    TT_MaxProfile                                                      */
+  /*                                                                       */
+  /*    FT_Sfnt_Tag                                                        */
+  /*    FT_Get_Sfnt_Table                                                  */
+  /*    FT_Load_Sfnt_Table                                                 */
+  /*    FT_Sfnt_Table_Info                                                 */
+  /*                                                                       */
+  /*    FT_Get_CMap_Language_ID                                            */
+  /*    FT_Get_CMap_Format                                                 */
+  /*                                                                       */
+  /*    FT_PARAM_TAG_UNPATENTED_HINTING                                    */
+  /*                                                                       */
   /*************************************************************************/
 
 
@@ -352,7 +371,7 @@
     FT_Short   xAvgCharWidth;
     FT_UShort  usWeightClass;
     FT_UShort  usWidthClass;
-    FT_Short   fsType;
+    FT_UShort  fsType;
     FT_Short   ySubscriptXSize;
     FT_Short   ySubscriptYSize;
     FT_Short   ySubscriptXOffset;
@@ -559,21 +578,44 @@
   /*    An enumeration used to specify the index of an SFNT table.         */
   /*    Used in the @FT_Get_Sfnt_Table API function.                       */
   /*                                                                       */
+  /* <Values>                                                              */
+  /*    FT_SFNT_HEAD :: To access the font's @TT_Header structure.         */
+  /*                                                                       */
+  /*    FT_SFNT_MAXP :: To access the font's @TT_MaxProfile structure.     */
+  /*                                                                       */
+  /*    FT_SFNT_OS2  :: To access the font's @TT_OS2 structure.            */
+  /*                                                                       */
+  /*    FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure.     */
+  /*                                                                       */
+  /*    FT_SFNT_VHEA :: To access the font's @TT_VertHeader structure.     */
+  /*                                                                       */
+  /*    FT_SFNT_POST :: To access the font's @TT_Postscript structure.     */
+  /*                                                                       */
+  /*    FT_SFNT_PCLT :: To access the font's @TT_PCLT structure.           */
+  /*                                                                       */
   typedef enum  FT_Sfnt_Tag_
   {
-    ft_sfnt_head = 0,    /* TT_Header     */
-    ft_sfnt_maxp = 1,    /* TT_MaxProfile */
-    ft_sfnt_os2  = 2,    /* TT_OS2        */
-    ft_sfnt_hhea = 3,    /* TT_HoriHeader */
-    ft_sfnt_vhea = 4,    /* TT_VertHeader */
-    ft_sfnt_post = 5,    /* TT_Postscript */
-    ft_sfnt_pclt = 6,    /* TT_PCLT       */
+    FT_SFNT_HEAD,
+    FT_SFNT_MAXP,
+    FT_SFNT_OS2,
+    FT_SFNT_HHEA,
+    FT_SFNT_VHEA,
+    FT_SFNT_POST,
+    FT_SFNT_PCLT,
 
-    sfnt_max   /* internal end mark */
+    FT_SFNT_MAX
 
   } FT_Sfnt_Tag;
 
-  /* */
+  /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag' */
+  /* values instead                                                      */
+#define ft_sfnt_head  FT_SFNT_HEAD
+#define ft_sfnt_maxp  FT_SFNT_MAXP
+#define ft_sfnt_os2   FT_SFNT_OS2
+#define ft_sfnt_hhea  FT_SFNT_HHEA
+#define ft_sfnt_vhea  FT_SFNT_VHEA
+#define ft_sfnt_post  FT_SFNT_POST
+#define ft_sfnt_pclt  FT_SFNT_PCLT
 
 
   /*************************************************************************/
@@ -611,7 +653,7 @@
   /*                                                                       */
   /*                                                                       */
   /*      vert_header =                                                    */
-  /*        (TT_VertHeader*)FT_Get_Sfnt_Table( face, ft_sfnt_vhea );       */
+  /*        (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA );       */
   /*    }                                                                  */
   /*                                                                       */
   FT_EXPORT( void* )
@@ -781,7 +823,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTTABLES_H__ */
+#endif /* TTTABLES_H_ */
 
 
 /* END */
diff --git a/include/tttags.h b/include/freetype/tttags.h
similarity index 97%
rename from include/tttags.h
rename to include/freetype/tttags.h
index d59aa19..f3c9aa5 100644
--- a/include/tttags.h
+++ b/include/freetype/tttags.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tags for TrueType and OpenType tables (specification only).          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2005, 2007, 2008, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTAGS_H__
-#define __TTAGS_H__
+#ifndef TTAGS_H_
+#define TTAGS_H_
 
 
 #include <ft2build.h>
@@ -105,7 +105,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTAGS_H__ */
+#endif /* TTAGS_H_ */
 
 
 /* END */
diff --git a/include/ttunpat.h b/include/freetype/ttunpat.h
similarity index 77%
rename from include/ttunpat.h
rename to include/freetype/ttunpat.h
index a016275..ca4676b 100644
--- a/include/ttunpat.h
+++ b/include/freetype/ttunpat.h
@@ -2,9 +2,10 @@
 /*                                                                         */
 /*  ttunpat.h                                                              */
 /*                                                                         */
-/*    Definitions for the unpatented TrueType hinting system               */
+/*    Definitions for the unpatented TrueType hinting system.              */
+/*    Obsolete, retained for backwards compatibility.                      */
 /*                                                                         */
-/*  Copyright 2003, 2006 by                                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  Written by Graham Asher <graham.asher@btinternet.com>                  */
@@ -18,8 +19,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTUNPAT_H__
-#define __TTUNPAT_H__
+#ifndef TTUNPAT_H_
+#define TTUNPAT_H_
 
 
 #include <ft2build.h>
@@ -41,19 +42,22 @@
   *   FT_PARAM_TAG_UNPATENTED_HINTING
   *
   * @description:
-  *   A constant used as the tag of an @FT_Parameter structure to indicate
-  *   that unpatented methods only should be used by the TrueType bytecode
-  *   interpreter for a typeface opened by @FT_Open_Face.
+  *   Deprecated.
+  *
+  *   Previously: A constant used as the tag of an @FT_Parameter structure to
+  *   indicate that unpatented methods only should be used by the TrueType
+  *   bytecode interpreter for a typeface opened by @FT_Open_Face.
   *
   */
 #define FT_PARAM_TAG_UNPATENTED_HINTING  FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
 
- /* */
+  /* */
+
 
 FT_END_HEADER
 
 
-#endif /* __TTUNPAT_H__ */
+#endif /* TTUNPAT_H_ */
 
 
 /* END */
diff --git a/include/ft2build.h b/include/ft2build.h
index 6f8eb7f..c89cb46 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType 2 build and setup macros.                                   */
 /*                                                                         */
-/*  Copyright 1996-2001, 2006, 2013 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,12 +31,12 @@
   /*************************************************************************/
 
 
-#ifndef __FT2BUILD_H__
-#define __FT2BUILD_H__
+#ifndef FT2BUILD_H_
+#define FT2BUILD_H_
 
-#include <config/ftheader.h>
+#include <freetype/config/ftheader.h>
 
-#endif /* __FT2BUILD_H__ */
+#endif /* FT2BUILD_H_ */
 
 
 /* END */
diff --git a/include/fterrors.h b/include/fterrors.h
deleted file mode 100644
index 0fa3e4d..0000000
--- a/include/fterrors.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  fterrors.h                                                             */
-/*                                                                         */
-/*    FreeType error code handling (specification).                        */
-/*                                                                         */
-/*  Copyright 1996-2002, 2004, 2007, 2013 by                               */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  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 special header file is used to define the handling of FT2        */
-  /* enumeration constants.  It can also be used to generate error message */
-  /* strings with a small macro trick explained below.                     */
-  /*                                                                       */
-  /* I - Error Formats                                                     */
-  /* -----------------                                                     */
-  /*                                                                       */
-  /*   The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be   */
-  /*   defined in ftoption.h in order to make the higher byte indicate     */
-  /*   the module where the error has happened (this is not compatible     */
-  /*   with standard builds of FreeType 2).  See the file `ftmoderr.h' for */
-  /*   more details.                                                       */
-  /*                                                                       */
-  /*                                                                       */
-  /* II - Error Message strings                                            */
-  /* --------------------------                                            */
-  /*                                                                       */
-  /*   The error definitions below are made through special macros that    */
-  /*   allow client applications to build a table of error message strings */
-  /*   if they need it.  The strings are not included in a normal build of */
-  /*   FreeType 2 to save space (most client applications do not use       */
-  /*   them).                                                              */
-  /*                                                                       */
-  /*   To do so, you have to define the following macros before including  */
-  /*   this file:                                                          */
-  /*                                                                       */
-  /*   FT_ERROR_START_LIST ::                                              */
-  /*     This macro is called before anything else to define the start of  */
-  /*     the error list.  It is followed by several FT_ERROR_DEF calls     */
-  /*     (see below).                                                      */
-  /*                                                                       */
-  /*   FT_ERROR_DEF( e, v, s ) ::                                          */
-  /*     This macro is called to define one single error.                  */
-  /*     `e' is the error code identifier (e.g. FT_Err_Invalid_Argument).  */
-  /*     `v' is the error numerical value.                                 */
-  /*     `s' is the corresponding error string.                            */
-  /*                                                                       */
-  /*   FT_ERROR_END_LIST ::                                                */
-  /*     This macro ends the list.                                         */
-  /*                                                                       */
-  /*   Additionally, you have to undefine __FTERRORS_H__ before #including */
-  /*   this file.                                                          */
-  /*                                                                       */
-  /*   Here is a simple example:                                           */
-  /*                                                                       */
-  /*     {                                                                 */
-  /*       #undef __FTERRORS_H__                                           */
-  /*       #define FT_ERRORDEF( e, v, s )  { e, s },                       */
-  /*       #define FT_ERROR_START_LIST     {                               */
-  /*       #define FT_ERROR_END_LIST       { 0, 0 } };                     */
-  /*                                                                       */
-  /*       const struct                                                    */
-  /*       {                                                               */
-  /*         int          err_code;                                        */
-  /*         const char*  err_msg;                                         */
-  /*       } ft_errors[] =                                                 */
-  /*                                                                       */
-  /*       #include FT_ERRORS_H                                            */
-  /*     }                                                                 */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#ifndef __FTERRORS_H__
-#define __FTERRORS_H__
-
-
-  /* include module base error codes */
-#include FT_MODULE_ERRORS_H
-
-
-  /*******************************************************************/
-  /*******************************************************************/
-  /*****                                                         *****/
-  /*****                       SETUP MACROS                      *****/
-  /*****                                                         *****/
-  /*******************************************************************/
-  /*******************************************************************/
-
-
-#undef  FT_NEED_EXTERN_C
-
-
-  /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
-  /* By default, we use `FT_Err_'.                            */
-  /*                                                          */
-#ifndef FT_ERR_PREFIX
-#define FT_ERR_PREFIX  FT_Err_
-#endif
-
-
-  /* FT_ERR_BASE is used as the base for module-specific errors. */
-  /*                                                             */
-#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
-
-#ifndef FT_ERR_BASE
-#define FT_ERR_BASE  FT_Mod_Err_Base
-#endif
-
-#else
-
-#undef FT_ERR_BASE
-#define FT_ERR_BASE  0
-
-#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */
-
-
-  /* If FT_ERRORDEF is not defined, we need to define a simple */
-  /* enumeration type.                                         */
-  /*                                                           */
-#ifndef FT_ERRORDEF
-
-#define FT_ERRORDEF( e, v, s )  e = v,
-#define FT_ERROR_START_LIST     enum {
-#define FT_ERROR_END_LIST       FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
-
-#ifdef __cplusplus
-#define FT_NEED_EXTERN_C
-  extern "C" {
-#endif
-
-#endif /* !FT_ERRORDEF */
-
-
-  /* this macro is used to define an error */
-#define FT_ERRORDEF_( e, v, s )                                             \
-          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
-
-  /* this is only used for <module>_Err_Ok, which must be 0! */
-#define FT_NOERRORDEF_( e, v, s )                             \
-          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
-
-
-#ifdef FT_ERROR_START_LIST
-  FT_ERROR_START_LIST
-#endif
-
-
-  /* now include the error codes */
-#include FT_ERROR_DEFINITIONS_H
-
-
-#ifdef FT_ERROR_END_LIST
-  FT_ERROR_END_LIST
-#endif
-
-
-  /*******************************************************************/
-  /*******************************************************************/
-  /*****                                                         *****/
-  /*****                      SIMPLE CLEANUP                     *****/
-  /*****                                                         *****/
-  /*******************************************************************/
-  /*******************************************************************/
-
-#ifdef FT_NEED_EXTERN_C
-  }
-#endif
-
-#undef FT_ERROR_START_LIST
-#undef FT_ERROR_END_LIST
-
-#undef FT_ERRORDEF
-#undef FT_ERRORDEF_
-#undef FT_NOERRORDEF_
-
-#undef FT_NEED_EXTERN_C
-#undef FT_ERR_BASE
-
-  /* FT_ERR_PREFIX is needed internally */
-#ifndef FT2_BUILD_LIBRARY
-#undef FT_ERR_PREFIX
-#endif
-
-#endif /* __FTERRORS_H__ */
-
-
-/* END */
diff --git a/include/ftlcdfil.h b/include/ftlcdfil.h
deleted file mode 100644
index 39206f0..0000000
--- a/include/ftlcdfil.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftlcdfil.h                                                             */
-/*                                                                         */
-/*    FreeType API for color filtering of subpixel bitmap glyphs           */
-/*    (specification).                                                     */
-/*                                                                         */
-/*  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,       */
-/*  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 __FT_LCD_FILTER_H__
-#define __FT_LCD_FILTER_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:
-   *   lcd_filtering
-   *
-   * @title:
-   *   LCD Filtering
-   *
-   * @abstract:
-   *   Reduce color fringes of LCD-optimized bitmaps.
-   *
-   * @description:
-   *   The @FT_Library_SetLcdFilter API can be used to specify a low-pass
-   *   filter, which is then applied to LCD-optimized bitmaps generated
-   *   through @FT_Render_Glyph.  This is useful to reduce color fringes
-   *   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
-   *   #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
-   *   in order to activate it.
-   *
-   *   FreeType generates alpha coverage maps, which are linear by nature.
-   *   For instance, the value 0x80 in bitmap representation means that
-   *   (within numerical precision) 0x80/0xff fraction of that pixel is
-   *   covered by the glyph's outline.  The blending function for placing
-   *   text over a background is
-   *
-   *   {
-   *     dst = alpha * src + (1 - alpha) * dst    ,
-   *   }
-   *
-   *   which is known as OVER.  However, when calculating the output of the
-   *   OVER operator, the source colors should first be transformed to a
-   *   linear color space, then alpha blended in that space, and transformed
-   *   back to the output color space.
-   *
-   *   When linear light blending is used, the default FIR5 filtering
-   *   weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as
-   *   they have been designed for black on white rendering while lacking
-   *   gamma correction.  To preserve color neutrality, weights for a FIR5
-   *   filter should be chosen according to two free parameters `a' and `c',
-   *   and the FIR weights should be
-   *
-   *   {
-   *     [a - c, a + c, 2 * a, a + c, a - c]    .
-   *   }
-   *
-   *   This formula generates equal weights for all the color primaries
-   *   across the filter kernel, which makes it colorless.  One suggested
-   *   set of weights is
-   *
-   *   {
-   *     [0x10, 0x50, 0x60, 0x50, 0x10]    ,
-   *   }
-   *
-   *   where `a' has value 0x30 and `b' value 0x20.  The weights in filter
-   *   may have a sum larger than 0x100, which increases coloration slightly
-   *   but also improves contrast.
-   */
-
-
-  /****************************************************************************
-   *
-   * @enum:
-   *   FT_LcdFilter
-   *
-   * @description:
-   *   A list of values to identify various types of LCD filters.
-   *
-   * @values:
-   *   FT_LCD_FILTER_NONE ::
-   *     Do not perform filtering.  When used with subpixel rendering, this
-   *     results in sometimes severe color fringes.
-   *
-   *   FT_LCD_FILTER_DEFAULT ::
-   *     The default filter reduces color fringes considerably, at the cost
-   *     of a slight blurriness in the output.
-   *
-   *   FT_LCD_FILTER_LIGHT ::
-   *     The light filter is a variant that produces less blurriness at the
-   *     cost of slightly more color fringes than the default one.  It might
-   *     be better, depending on taste, your monitor, or your personal vision.
-   *
-   *   FT_LCD_FILTER_LEGACY ::
-   *     This filter corresponds to the original libXft color filter.  It
-   *     provides high contrast output but can exhibit really bad color
-   *     fringes if glyphs are not extremely well hinted to the pixel grid.
-   *     In other words, it only works well if the TrueType bytecode
-   *     interpreter is enabled *and* high-quality hinted fonts are used.
-   *
-   *     This filter is only provided for comparison purposes, and might be
-   *     disabled or stay unsupported in the future.
-   *
-   * @since:
-   *   2.3.0
-   */
-  typedef enum  FT_LcdFilter_
-  {
-    FT_LCD_FILTER_NONE    = 0,
-    FT_LCD_FILTER_DEFAULT = 1,
-    FT_LCD_FILTER_LIGHT   = 2,
-    FT_LCD_FILTER_LEGACY  = 16,
-
-    FT_LCD_FILTER_MAX   /* do not remove */
-
-  } FT_LcdFilter;
-
-
-  /**************************************************************************
-   *
-   * @func:
-   *   FT_Library_SetLcdFilter
-   *
-   * @description:
-   *   This function is used to apply color filtering to LCD decimated
-   *   bitmaps, like the ones used when calling @FT_Render_Glyph with
-   *   @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V.
-   *
-   * @input:
-   *   library ::
-   *     A handle to the target library instance.
-   *
-   *   filter ::
-   *     The filter type.
-   *
-   *     You can use @FT_LCD_FILTER_NONE here to disable this feature, or
-   *     @FT_LCD_FILTER_DEFAULT to use a default filter that should work
-   *     well on most LCD screens.
-   *
-   * @return:
-   *   FreeType error code.  0~means success.
-   *
-   * @note:
-   *   This feature is always disabled by default.  Clients must make an
-   *   explicit call to this function with a `filter' value other than
-   *   @FT_LCD_FILTER_NONE in order to enable it.
-   *
-   *   Due to *PATENTS* covering subpixel rendering, this function doesn't
-   *   do anything except returning `FT_Err_Unimplemented_Feature' if the
-   *   configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
-   *   defined in your build of the library, which should correspond to all
-   *   default builds of FreeType.
-   *
-   *   The filter affects glyph bitmaps rendered through @FT_Render_Glyph,
-   *   @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char.
-   *
-   *   It does _not_ affect the output of @FT_Outline_Render and
-   *   @FT_Outline_Get_Bitmap.
-   *
-   *   If this feature is activated, the dimensions of LCD glyph bitmaps are
-   *   either larger or taller than the dimensions of the corresponding
-   *   outline with regards to the pixel grid.  For example, for
-   *   @FT_RENDER_MODE_LCD, the filter adds up to 3~pixels to the left, and
-   *   up to 3~pixels to the right.
-   *
-   *   The bitmap offset values are adjusted correctly, so clients shouldn't
-   *   need to modify their layout and glyph positioning code when enabling
-   *   the filter.
-   *
-   * @since:
-   *   2.3.0
-   */
-  FT_EXPORT( FT_Error )
-  FT_Library_SetLcdFilter( FT_Library    library,
-                           FT_LcdFilter  filter );
-
-
-  /**************************************************************************
-   *
-   * @func:
-   *   FT_Library_SetLcdFilterWeights
-   *
-   * @description:
-   *   Use this function to override the filter weights selected by
-   *   @FT_Library_SetLcdFilter.  By default, FreeType uses the quintuple
-   *   (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10,
-   *   0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and
-   *   FT_LCD_FILTER_LEGACY.
-   *
-   * @input:
-   *   library ::
-   *     A handle to the target library instance.
-   *
-   *   weights ::
-   *     A pointer to an array; the function copies the first five bytes and
-   *     uses them to specify the filter weights.
-   *
-   * @return:
-   *   FreeType error code.  0~means success.
-   *
-   * @note:
-   *   Due to *PATENTS* covering subpixel rendering, this function doesn't
-   *   do anything except returning `FT_Err_Unimplemented_Feature' if the
-   *   configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
-   *   defined in your build of the library, which should correspond to all
-   *   default builds of FreeType.
-   *
-   *   This function must be called after @FT_Library_SetLcdFilter to have
-   *   any effect.
-   *
-   * @since:
-   *   2.4.0
-   */
-  FT_EXPORT( FT_Error )
-  FT_Library_SetLcdFilterWeights( FT_Library      library,
-                                  unsigned char  *weights );
-
-  /* */
-
-
-FT_END_HEADER
-
-#endif /* __FT_LCD_FILTER_H__ */
-
-
-/* END */
diff --git a/include/ftttdrv.h b/include/ftttdrv.h
deleted file mode 100644
index 70ad3d5..0000000
--- a/include/ftttdrv.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftttdrv.h                                                              */
-/*                                                                         */
-/*    FreeType API for controlling the TrueType driver                     */
-/*    (specification only).                                                */
-/*                                                                         */
-/*  Copyright 2013 by                                                      */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifndef __FTTTDRV_H__
-#define __FTTTDRV_H__
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
-  /**************************************************************************
-   *
-   * @section:
-   *   tt_driver
-   *
-   * @title:
-   *   The TrueType driver
-   *
-   * @abstract:
-   *   Controlling the TrueType driver module.
-   *
-   * @description:
-   *   While FreeType's TrueType driver doesn't expose API functions by
-   *   itself, it is possible to control its behaviour with @FT_Property_Set
-   *   and @FT_Property_Get.  The following lists the available properties
-   *   together with the necessary macros and structures.
-   *
-   *   The TrueType driver's module name is `truetype'.
-   *
-   */
-
-
-  /**************************************************************************
-   *
-   * @property:
-   *   interpreter-version
-   *
-   * @description:
-   *   Currently, two versions are available, 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
-   *   support otherwise (since it isn't available then).
-   *
-   *   If subpixel hinting is on, many TrueType bytecode instructions
-   *   behave differently compared to B/W or grayscale rendering.  The
-   *   main idea is to render at a much increased horizontal resolution,
-   *   then sampling down the created output to subpixel precision.
-   *   However, many older fonts are not suited to this and must be
-   *   specially taken care of by applying (hardcoded) font-specific
-   *   tweaks.
-   *
-   *   Details on subpixel hinting and some of the necessary tweaks can be
-   *   found in Greg Hitchcock's whitepaper at
-   *   `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
-   *
-   *   The following example code demonstrates how to activate subpixel
-   *   hinting (omitting the error handling).
-   *
-   *   {
-   *     FT_Library  library;
-   *     FT_Face     face;
-   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_38;
-   *
-   *
-   *     FT_Init_FreeType( &library );
-   *
-   *     FT_Property_Set( library, "truetype",
-   *                               "interpreter-version",
-   *                               &interpreter_version );
-   *   }
-   *
-   * @note:
-   *   This property can be used with @FT_Property_Get also.
-   *
-   */
-
-
-  /**************************************************************************
-   *
-   * @enum:
-   *   TT_INTERPRETER_VERSION_XXX
-   *
-   * @description:
-   *   A list of constants used for the @interpreter-version property to
-   *   select the hinting engine for Truetype fonts.
-   *
-   *   The numeric value in the constant names represents the version
-   *   number as returned by the `GETINFO' bytecode instruction.
-   *
-   * @values:
-   *   TT_INTERPRETER_VERSION_35 ::
-   *     Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
-   *     Windows~98; only grayscale and B/W rasterizing is supported.
-   *
-   *   TT_INTERPRETER_VERSION_38 ::
-   *     Version~38 corresponds to MS rasterizer v.1.9; it is roughly
-   *     equivalent to the hinting provided by DirectWrite ClearType (as
-   *     can be found, for example, in the Internet Explorer~9 running on
-   *     Windows~7).
-   *
-   * @note:
-   *   This property controls the behaviour of the bytecode interpreter
-   *   and thus how outlines get hinted.  It does *not* control how glyph
-   *   get rasterized!  In particular, it does not control subpixel color
-   *   filtering.
-   *
-   *   If FreeType has not been compiled with configuration option
-   *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
-   *   `FT_Err_Unimplemented_Feature' error.
-   *
-   *   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
-
-
- /* */
-
-FT_END_HEADER
-
-
-#endif /* __FTTTDRV_H__ */
-
-
-/* END */
diff --git a/include/internal/ftcalc.h b/include/internal/ftcalc.h
deleted file mode 100644
index 03bd68e..0000000
--- a/include/internal/ftcalc.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftcalc.h                                                               */
-/*                                                                         */
-/*    Arithmetic computations (specification).                             */
-/*                                                                         */
-/*  Copyright 1996-2006, 2008, 2009, 2012-2013 by                          */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  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 __FTCALC_H__
-#define __FTCALC_H__
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-
-FT_BEGIN_HEADER
-
-
-#if 0
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    FT_SqrtFixed                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the square root of a 16.16 fixed-point value.             */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    x :: The value to compute the root for.                            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The result of `sqrt(x)'.                                           */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    This function is not very fast.                                    */
-  /*                                                                       */
-  FT_BASE( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x );
-
-#endif /* 0 */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    FT_MulDiv_No_Round                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A very simple function used to perform the computation `(a*b)/c'   */
-  /*    (without rounding) with maximum accuracy (it uses a 64-bit         */
-  /*    intermediate integer whenever necessary).                          */
-  /*                                                                       */
-  /*    This function isn't necessarily as fast as some processor specific */
-  /*    operations, but is at least completely portable.                   */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    a :: The first multiplier.                                         */
-  /*    b :: The second multiplier.                                        */
-  /*    c :: The divisor.                                                  */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The result of `(a*b)/c'.  This function never traps when trying to */
-  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
-  /*    on the signs of `a' and `b'.                                       */
-  /*                                                                       */
-  FT_BASE( FT_Long )
-  FT_MulDiv_No_Round( FT_Long  a,
-                      FT_Long  b,
-                      FT_Long  c );
-
-
-  /*
-   *  A variant of FT_Matrix_Multiply which scales its result afterwards.
-   *  The idea is that both `a' and `b' are scaled by factors of 10 so that
-   *  the values are as precise as possible to get a correct result during
-   *  the 64bit multiplication.  Let `sa' and `sb' be the scaling factors of
-   *  `a' and `b', respectively, then the scaling factor of the result is
-   *  `sa*sb'.
-   */
-  FT_BASE( void )
-  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
-                             FT_Matrix        *b,
-                             FT_Long           scaling );
-
-
-  /*
-   *  A variant of FT_Vector_Transform.  See comments for
-   *  FT_Matrix_Multiply_Scaled.
-   */
-  FT_BASE( void )
-  FT_Vector_Transform_Scaled( FT_Vector*        vector,
-                              const FT_Matrix*  matrix,
-                              FT_Long           scaling );
-
-
-  /*
-   *  Return -1, 0, or +1, depending on the orientation of a given corner.
-   *  We use the Cartesian coordinate system, with positive vertical values
-   *  going upwards.  The function returns +1 if the corner turns to the
-   *  left, -1 to the right, and 0 for undecidable cases.
-   */
-  FT_BASE( FT_Int )
-  ft_corner_orientation( FT_Pos  in_x,
-                         FT_Pos  in_y,
-                         FT_Pos  out_x,
-                         FT_Pos  out_y );
-
-  /*
-   *  Return TRUE if a corner is flat or nearly flat.  This is equivalent to
-   *  saying that the angle difference between the `in' and `out' vectors is
-   *  very small.
-   */
-  FT_BASE( FT_Int )
-  ft_corner_is_flat( FT_Pos  in_x,
-                     FT_Pos  in_y,
-                     FT_Pos  out_x,
-                     FT_Pos  out_y );
-
-
-  /*
-   *  Return the most significant bit index.
-   */
-  FT_BASE( FT_Int )
-  FT_MSB( FT_UInt32  z );
-
-
-  /*
-   *  Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
-   *  two fixed-point arguments instead.
-   */
-  FT_BASE( FT_Fixed )
-  FT_Hypot( FT_Fixed  x,
-            FT_Fixed  y );
-
-
-#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
-#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
-#define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
-#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) << 2  )
-#define FLOAT_TO_FIXED( x )    ( (FT_Long)( x * 65536.0 ) )
-#define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )
-
-#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
-                                        : ( -( ( 32 - (x) ) & -64 ) ) )
-
-
-FT_END_HEADER
-
-#endif /* __FTCALC_H__ */
-
-
-/* END */
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index b44a5ba..b856e57 100644
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -5,7 +5,7 @@
 /*    Routines used to compute vector angles with limited accuracy         */
 /*    and very high speed.  It also contains sorting routines (body).      */
 /*                                                                         */
-/*  Copyright 2003-2006, 2011-2012 by                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,66 +20,6 @@
 #include "aftypes.h"
 
 
-#if 0
-
-  FT_LOCAL_DEF( FT_Int )
-  af_corner_is_flat( FT_Pos  x_in,
-                     FT_Pos  y_in,
-                     FT_Pos  x_out,
-                     FT_Pos  y_out )
-  {
-    FT_Pos  ax = x_in;
-    FT_Pos  ay = y_in;
-
-    FT_Pos  d_in, d_out, d_corner;
-
-
-    if ( ax < 0 )
-      ax = -ax;
-    if ( ay < 0 )
-      ay = -ay;
-    d_in = ax + ay;
-
-    ax = x_out;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = y_out;
-    if ( ay < 0 )
-      ay = -ay;
-    d_out = ax + ay;
-
-    ax = x_out + x_in;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = y_out + y_in;
-    if ( ay < 0 )
-      ay = -ay;
-    d_corner = ax + ay;
-
-    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
-  }
-
-
-  FT_LOCAL_DEF( FT_Int )
-  af_corner_orientation( FT_Pos  x_in,
-                         FT_Pos  y_in,
-                         FT_Pos  x_out,
-                         FT_Pos  y_out )
-  {
-    FT_Pos  delta;
-
-
-    delta = x_in * y_out - y_in * x_out;
-
-    if ( delta == 0 )
-      return 0;
-    else
-      return 1 - 2 * ( delta < 0 );
-  }
-
-#endif /* 0 */
-
-
   /*
    *  We are not using `af_angle_atan' anymore, but we keep the source
    *  code below just in case...
@@ -319,7 +259,7 @@
           sum         += table[j].org;
           table[j].org = 0;
         }
-        table[cur_idx].org = sum / j;
+        table[cur_idx].org = sum / (FT_Pos)j;
 
         if ( i < *count - 1 )
         {
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
index f3526bf..7719c02 100644
--- a/src/autofit/afblue.c
+++ b/src/autofit/afblue.c
@@ -7,7 +7,7 @@
 /*                                                                         */
 /*    Auto-fitter data for blue strings (body).                            */
 /*                                                                         */
-/*  Copyright 2013 by                                                      */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,85 +26,249 @@
   af_blue_strings[] =
   {
     /* */
-    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕПЗОСЭ */
+    '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8',  /* ا إ ل ك ط ظ */
     '\0',
-    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕШЗОСЭ */
+    '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83',  /* ت ث ط ظ ك */
     '\0',
-    '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81',  /* хпншезос */
+    '\xD9', '\x80',  /* ـ */
     '\0',
-    '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84',  /* руф */
+    '\xD4', '\xB1', ' ', '\xD5', '\x84', ' ', '\xD5', '\x92', ' ', '\xD5', '\x8D', ' ', '\xD4', '\xB2', ' ', '\xD4', '\xB3', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x95',  /* Ա Մ Ւ Ս Բ Գ Դ Օ */
     '\0',
-    '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6',  /* क म अ आ थ ध भ श */
+    '\xD5', '\x92', ' ', '\xD5', '\x88', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x83', ' ', '\xD5', '\x87', ' ', '\xD5', '\x8D', ' ', '\xD5', '\x8F', ' ', '\xD5', '\x95',  /* Ւ Ո Դ Ճ Շ Ս Տ Օ */
     '\0',
-    '\xE0', '\xA4', '\x88', '\xE0', '\xA4', '\x90', '\xE0', '\xA4', '\x93', '\xE0', '\xA4', '\x94', '\xE0', '\xA4', '\xBF', '\xE0', '\xA5', '\x80', '\xE0', '\xA5', '\x8B', '\xE0', '\xA5', '\x8C',  /* ई ऐ ओ औ ि ी ो ौ */
+    '\xD5', '\xA5', ' ', '\xD5', '\xA7', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xB4', ' ', '\xD5', '\xBE', ' ', '\xD6', '\x86', ' ', '\xD5', '\xB3',  /* ե է ի մ վ ֆ ճ */
     '\0',
-    '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6',  /* क म अ आ थ ध भ श */
+    '\xD5', '\xA1', ' ', '\xD5', '\xB5', ' ', '\xD6', '\x82', ' ', '\xD5', '\xBD', ' ', '\xD5', '\xA3', ' ', '\xD5', '\xB7', ' ', '\xD6', '\x80', ' ', '\xD6', '\x85',  /* ա յ ւ ս գ շ ր օ */
     '\0',
-    '\xE0', '\xA5', '\x81', '\xE0', '\xA5', '\x83',  /* ु ृ */
+    '\xD5', '\xB0', ' ', '\xD5', '\xB8', ' ', '\xD5', '\xB3', ' ', '\xD5', '\xA1', ' ', '\xD5', '\xA5', ' ', '\xD5', '\xAE', ' ', '\xD5', '\xBD', ' ', '\xD6', '\x85',  /* հ ո ճ ա ե ծ ս օ */
     '\0',
-    '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9',  /* ΓΒΕΖΘΟΩ */
+    '\xD5', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81',  /* բ ը ի լ ղ պ փ ց */
     '\0',
-    '\xCE', '\x92', '\xCE', '\x94', '\xCE', '\x96', '\xCE', '\x9E', '\xCE', '\x98', '\xCE', '\x9F',  /* ΒΔΖΞΘΟ */
+    '\xE0', '\xA6', '\x85', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xAD', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95',  /* অ ড ত ন ব ভ ল ক */
     '\0',
-    '\xCE', '\xB2', '\xCE', '\xB8', '\xCE', '\xB4', '\xCE', '\xB6', '\xCE', '\xBB', '\xCE', '\xBE',  /* βθδζλξ */
+    '\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97',  /* ই ট ঠ ি ী ৈ ৗ */
     '\0',
-    '\xCE', '\xB1', '\xCE', '\xB5', '\xCE', '\xB9', '\xCE', '\xBF', '\xCF', '\x80', '\xCF', '\x83', '\xCF', '\x84', '\xCF', '\x89',  /* αειοπστω */
+    '\xE0', '\xA6', '\x93', ' ', '\xE0', '\xA6', '\x8F', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95',  /* ও এ ড ত ন ব ল ক */
     '\0',
-    '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88',  /* βγημρφχψ */
+    '\xE1', '\x8F', '\x86', ' ', '\xE1', '\x8E', '\xBB', ' ', '\xE1', '\x8E', '\xAC', ' ', '\xE1', '\x8F', '\x83', ' ', '\xE1', '\x8E', '\xA4', ' ', '\xE1', '\x8F', '\xA3', ' ', '\xE1', '\x8E', '\xA6', ' ', '\xE1', '\x8F', '\x95',  /* Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ */
     '\0',
-    '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1',  /* בדהחךכםס */
+    '\xEA', '\xAE', '\x92', ' ', '\xEA', '\xAE', '\xA4', ' ', '\xEA', '\xAE', '\xB6', ' ', '\xEA', '\xAD', '\xB4', ' ', '\xEA', '\xAD', '\xBE', ' ', '\xEA', '\xAE', '\x97', ' ', '\xEA', '\xAE', '\x9D', ' ', '\xEA', '\xAE', '\xBF',  /* ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ */
     '\0',
-    '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6',  /* בטכםסצ */
+    '\xEA', '\xAE', '\x96', ' ', '\xEA', '\xAD', '\xBC', ' ', '\xEA', '\xAE', '\x93', ' ', '\xEA', '\xAE', '\xA0', ' ', '\xEA', '\xAE', '\xB3', ' ', '\xEA', '\xAD', '\xB6', ' ', '\xEA', '\xAE', '\xA5', ' ', '\xEA', '\xAE', '\xBB',  /* ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ */
     '\0',
-    '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5',  /* קךןףץ */
+    '\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB',  /* ᏸ ꮐ ꭹ ꭻ */
     '\0',
-    'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S',  /* THEZOCQS */
+    '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е П З О С Э */
     '\0',
-    'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S',  /* HEZLOCUS */
+    '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е Ш З О С Э */
     '\0',
-    'f', 'i', 'j', 'k', 'd', 'b', 'h',  /* fijkdbh */
+    '\xD1', '\x85', ' ', '\xD0', '\xBF', ' ', '\xD0', '\xBD', ' ', '\xD1', '\x88', ' ', '\xD0', '\xB5', ' ', '\xD0', '\xB7', ' ', '\xD0', '\xBE', ' ', '\xD1', '\x81',  /* х п н ш е з о с */
     '\0',
-    'x', 'z', 'r', 'o', 'e', 's', 'c',  /* xzroesc */
+    '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84',  /* р у ф */
     '\0',
-    'p', 'q', 'g', 'j', 'y',  /* pqgjy */
+    '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6',  /* क म अ आ थ ध भ श */
+    '\0',
+    '\xE0', '\xA4', '\x88', ' ', '\xE0', '\xA4', '\x90', ' ', '\xE0', '\xA4', '\x93', ' ', '\xE0', '\xA4', '\x94', ' ', '\xE0', '\xA4', '\xBF', ' ', '\xE0', '\xA5', '\x80', ' ', '\xE0', '\xA5', '\x8B', ' ', '\xE0', '\xA5', '\x8C',  /* ई ऐ ओ औ ि ी ो ौ */
+    '\0',
+    '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6',  /* क म अ आ थ ध भ श */
+    '\0',
+    '\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83',  /* ु ृ */
+    '\0',
+    '\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\x83', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x8D', '\x90', ' ', '\xE1', '\x88', '\x9B', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x8B', ' ', '\xE1', '\x8B', '\x90',  /* ሀ ሃ ዘ ፐ ማ በ ዋ ዐ */
+    '\0',
+    '\xE1', '\x88', '\x88', ' ', '\xE1', '\x88', '\x90', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\xAA', ' ', '\xE1', '\x8B', '\x90', ' ', '\xE1', '\x8C', '\xA8',  /* ለ ሐ በ ዘ ሀ ሪ ዐ ጨ */
+    '\0',
+    '\xE1', '\x83', '\x92', ' ', '\xE1', '\x83', '\x93', ' ', '\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x97', ' ', '\xE1', '\x83', '\x98', ' ', '\xE1', '\x83', '\x9D', ' ', '\xE1', '\x83', '\xA6',  /* გ დ ე ვ თ ი ო ღ */
+    '\0',
+    '\xE1', '\x83', '\x90', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xAB', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\x9E',  /* ა ზ მ ს შ ძ ხ პ */
+    '\0',
+    '\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xA9', ' ', '\xE1', '\x83', '\xAC',  /* ს ხ ქ ზ მ შ ჩ წ */
+    '\0',
+    '\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x9F', ' ', '\xE1', '\x83', '\xA2', ' ', '\xE1', '\x83', '\xA3', ' ', '\xE1', '\x83', '\xA4', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\xA7',  /* ე ვ ჟ ტ უ ფ ქ ყ */
+    '\0',
+    '\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xB9', ' ', '\xE1', '\x82', '\xBC', ' ', '\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xB3', ' ', '\xE1', '\x82', '\xBA',  /* Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ */
+    '\0',
+    '\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xA8', ' ', '\xE1', '\x82', '\xA6', ' ', '\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xAA', ' ', '\xE1', '\x82', '\xAB',  /* Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ */
+    '\0',
+    '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x97', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x87', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x96',  /* ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ */
+    '\0',
+    '\xE2', '\xB4', '\x88', ' ', '\xE2', '\xB4', '\x8C', ' ', '\xE2', '\xB4', '\x96', ' ', '\xE2', '\xB4', '\x8E', ' ', '\xE2', '\xB4', '\x83', ' ', '\xE2', '\xB4', '\x86', ' ', '\xE2', '\xB4', '\x8B', ' ', '\xE2', '\xB4', '\xA2',  /* ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ */
+    '\0',
+    '\xE2', '\xB4', '\x90', ' ', '\xE2', '\xB4', '\x91', ' ', '\xE2', '\xB4', '\x93', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x99', ' ', '\xE2', '\xB4', '\x9B', ' ', '\xE2', '\xB4', '\xA1', ' ', '\xE2', '\xB4', '\xA3',  /* ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ */
+    '\0',
+    '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D',  /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */
+    '\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',
+    '\xE0', '\xAA', '\xA4', ' ', '\xE0', '\xAA', '\xA8', ' ', '\xE0', '\xAA', '\x8B', ' ', '\xE0', '\xAA', '\x8C', ' ', '\xE0', '\xAA', '\x9B', ' ', '\xE0', '\xAA', '\x9F', ' ', '\xE0', '\xAA', '\xB0', ' ', '\xE0', '\xAB', '\xA6',  /* ત ન ઋ ઌ છ ટ ર ૦ */
+    '\0',
+    '\xE0', '\xAA', '\x96', ' ', '\xE0', '\xAA', '\x97', ' ', '\xE0', '\xAA', '\x98', ' ', '\xE0', '\xAA', '\x9E', ' ', '\xE0', '\xAA', '\x87', ' ', '\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\xA0', ' ', '\xE0', '\xAA', '\x9C',  /* ખ ગ ઘ ઞ ઇ ઈ ઠ જ */
+    '\0',
+    '\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\x8A', ' ', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB2', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB6', '\xE0', '\xAB', '\x8D', '\xE0', '\xAA', '\x9A', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\x9C', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\xB8', '\xE0', '\xAB', '\x80',  /* ઈ ઊ િ ી લી શ્ચિ જિ સી */
+    '\0',
+    '\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAB', '\x84', ' ', '\xE0', '\xAA', '\x96', '\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x84',  /* ુ ૃ ૄ ખુ છૃ છૄ */
+    '\0',
+    '\xE0', '\xAB', '\xA6', ' ', '\xE0', '\xAB', '\xA7', ' ', '\xE0', '\xAB', '\xA8', ' ', '\xE0', '\xAB', '\xA9', ' ', '\xE0', '\xAB', '\xAD',  /* ૦ ૧ ૨ ૩ ૭ */
+    '\0',
+    '\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8',  /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
+    '\0',
+    '\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8',  /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
+    '\0',
+    '\xE0', '\xA8', '\x87', ' ', '\xE0', '\xA8', '\x88', ' ', '\xE0', '\xA8', '\x89', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA9', '\xB3', ' ', '\xE0', '\xA8', '\xBF', ' ', '\xE0', '\xA9', '\x80',  /* ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ */
+    '\0',
+    '\xE0', '\xA8', '\x85', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA0', ' ', '\xE0', '\xA8', '\xB0', ' ', '\xE0', '\xA8', '\xB8',  /* ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ */
+    '\0',
+    '\xE0', '\xA9', '\xA6', ' ', '\xE0', '\xA9', '\xA7', ' ', '\xE0', '\xA9', '\xA8', ' ', '\xE0', '\xA9', '\xA9', ' ', '\xE0', '\xA9', '\xAD',  /* ੦ ੧ ੨ ੩ ੭ */
+    '\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',  /* ק ך ן ף ץ */
+    '\0',
+    '\xE0', '\xB2', '\x87', ' ', '\xE0', '\xB2', '\x8A', ' ', '\xE0', '\xB2', '\x90', ' ', '\xE0', '\xB2', '\xA3', ' ', '\xE0', '\xB2', '\xB8', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xA8', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xA6', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xB0', '\xE0', '\xB2', '\xBE',  /* ಇ ಊ ಐ ಣ ಸಾ ನಾ ದಾ ರಾ */
+    '\0',
+    '\xE0', '\xB2', '\x85', ' ', '\xE0', '\xB2', '\x89', ' ', '\xE0', '\xB2', '\x8E', ' ', '\xE0', '\xB2', '\xB2', ' ', '\xE0', '\xB3', '\xA6', ' ', '\xE0', '\xB3', '\xA8', ' ', '\xE0', '\xB3', '\xAC', ' ', '\xE0', '\xB3', '\xAD',  /* ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭ */
+    '\0',
+    '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6',  /* ខ ទ ន ឧ ឩ ា */
+    '\0',
+    '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90',  /* ក្ក ក្ខ ក្គ ក្ថ */
+    '\0',
+    '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2',  /* ខ ឃ ច ឋ ប ម យ ឲ */
+    '\0',
+    '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF',  /* ត្រ រៀ ឲ្យ អឿ */
+    '\0',
+    '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x83', ' ', '\xE1', '\x9E', '\x84', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x85', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9E', '\xBF', ' ', '\xE1', '\x9E', '\x9B', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9E', '\xBF',  /* ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ */
+    '\0',
+    '\xE1', '\xA7', '\xA0', ' ', '\xE1', '\xA7', '\xA1',  /* ᧠ ᧡ */
+    '\0',
+    '\xE1', '\xA7', '\xB6', ' ', '\xE1', '\xA7', '\xB9',  /* ᧶ ᧹ */
+    '\0',
+    '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\x94', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\xA1', ' ', '\xE0', '\xBA', '\xA5', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\x87',  /* າ ດ ອ ມ ລ ວ ຣ ງ */
+    '\0',
+    '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\x9A', ' ', '\xE0', '\xBA', '\x8D', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\xAE', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA2',  /* າ ອ ບ ຍ ຣ ຮ ວ ຢ */
+    '\0',
+    '\xE0', '\xBA', '\x9B', ' ', '\xE0', '\xBA', '\xA2', ' ', '\xE0', '\xBA', '\x9F', ' ', '\xE0', '\xBA', '\x9D',  /* ປ ຢ ຟ ຝ */
+    '\0',
+    '\xE0', '\xBB', '\x82', ' ', '\xE0', '\xBB', '\x84', ' ', '\xE0', '\xBB', '\x83',  /* ໂ ໄ ໃ */
+    '\0',
+    '\xE0', '\xBA', '\x87', ' ', '\xE0', '\xBA', '\x8A', ' ', '\xE0', '\xBA', '\x96', ' ', '\xE0', '\xBA', '\xBD', ' ', '\xE0', '\xBB', '\x86', ' ', '\xE0', '\xBA', '\xAF',  /* ງ ຊ ຖ ຽ ໆ ຯ */
+    '\0',
+    'T', ' ', 'H', ' ', 'E', ' ', 'Z', ' ', 'O', ' ', 'C', ' ', 'Q', ' ', 'S',  /* T H E Z O C Q S */
+    '\0',
+    'H', ' ', 'E', ' ', 'Z', ' ', 'L', ' ', 'O', ' ', 'C', ' ', 'U', ' ', 'S',  /* H E Z L O C U S */
+    '\0',
+    'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h',  /* f i j k d b h */
+    '\0',
+    'x', ' ', 'z', ' ', 'r', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c',  /* x z r o e s c */
+    '\0',
+    'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y',  /* p q g j y */
+    '\0',
+    '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x85', ' ', '\xE2', '\x82', '\x87', ' ', '\xE2', '\x82', '\x88',  /* ₀ ₃ ₅ ₇ ₈ */
+    '\0',
+    '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x81', ' ', '\xE2', '\x82', '\x82', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x88',  /* ₀ ₁ ₂ ₃ ₈ */
+    '\0',
+    '\xE1', '\xB5', '\xA2', ' ', '\xE2', '\xB1', '\xBC', ' ', '\xE2', '\x82', '\x95', ' ', '\xE2', '\x82', '\x96', ' ', '\xE2', '\x82', '\x97',  /* ᵢ ⱼ ₕ ₖ ₗ */
+    '\0',
+    '\xE2', '\x82', '\x90', ' ', '\xE2', '\x82', '\x91', ' ', '\xE2', '\x82', '\x92', ' ', '\xE2', '\x82', '\x93', ' ', '\xE2', '\x82', '\x99', ' ', '\xE2', '\x82', '\x9B', ' ', '\xE1', '\xB5', '\xA5', ' ', '\xE1', '\xB5', '\xA4', ' ', '\xE1', '\xB5', '\xA3',  /* ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ */
+    '\0',
+    '\xE1', '\xB5', '\xA6', ' ', '\xE1', '\xB5', '\xA7', ' ', '\xE1', '\xB5', '\xA8', ' ', '\xE1', '\xB5', '\xA9', ' ', '\xE2', '\x82', '\x9A',  /* ᵦ ᵧ ᵨ ᵩ ₚ */
+    '\0',
+    '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB3', ' ', '\xE2', '\x81', '\xB5', ' ', '\xE2', '\x81', '\xB7', ' ', '\xE1', '\xB5', '\x80', ' ', '\xE1', '\xB4', '\xB4', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xBC',  /* ⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ */
+    '\0',
+    '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB9', ' ', '\xC2', '\xB2', ' ', '\xC2', '\xB3', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xB8', ' ', '\xE1', '\xB4', '\xBC', ' ', '\xE1', '\xB5', '\x81',  /* ⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ */
+    '\0',
+    '\xE1', '\xB5', '\x87', ' ', '\xE1', '\xB5', '\x88', ' ', '\xE1', '\xB5', '\x8F', ' ', '\xCA', '\xB0', ' ', '\xCA', '\xB2', ' ', '\xE1', '\xB6', '\xA0', ' ', '\xE2', '\x81', '\xB1',  /* ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ */
+    '\0',
+    '\xE1', '\xB5', '\x89', ' ', '\xE1', '\xB5', '\x92', ' ', '\xCA', '\xB3', ' ', '\xCB', '\xA2', ' ', '\xCB', '\xA3', ' ', '\xE1', '\xB6', '\x9C', ' ', '\xE1', '\xB6', '\xBB',  /* ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ */
+    '\0',
+    '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D',  /* ᵖ ʸ ᵍ */
+    '\0',
+    '\xE0', '\xB4', '\x92', ' ', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xB1', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', ' ', '\xE0', '\xB4', '\x9A', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\xAA',  /* ഒ ട ഠ റ ച പ ച്ച പ്പ */
+    '\0',
+    '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xA7', ' ', '\xE0', '\xB4', '\xB6', ' ', '\xE0', '\xB4', '\x98', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xA5', ' ', '\xE0', '\xB4', '\xB2',  /* ട ഠ ധ ശ ഘ ച ഥ ല */
+    '\0',
+    '\xE1', '\x80', '\x81', ' ', '\xE1', '\x80', '\x82', ' ', '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\xA5', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B',  /* ခ ဂ င ဒ ဝ ၥ ၊ ။ */
+    '\0',
+    '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x8E', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x95', ' ', '\xE1', '\x80', '\x97', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B',  /* င ဎ ဒ ပ ဗ ဝ ၊ ။ */
+    '\0',
+    '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xBC', ' ', '\xE1', '\x81', '\x8D', ' ', '\xE1', '\x81', '\x8F', ' ', '\xE1', '\x81', '\x86', ' ', '\xE1', '\x80', '\xAB', ' ', '\xE1', '\x80', '\xAD',  /* ဩ ြ ၍ ၏ ၆ ါ ိ */
+    '\0',
+    '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89',  /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */
+    '\0',
+    '\xE0', '\xB6', '\x89', ' ', '\xE0', '\xB6', '\x9A', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\xB4', ' ', '\xE0', '\xB6', '\xBA', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB7', '\x86',  /* ඉ ක ඝ ඳ ප ය ල ෆ */
+    '\0',
+    '\xE0', '\xB6', '\x91', ' ', '\xE0', '\xB6', '\x94', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xA2', ' ', '\xE0', '\xB6', '\xA7', ' ', '\xE0', '\xB6', '\xAE', ' ', '\xE0', '\xB6', '\xB0', ' ', '\xE0', '\xB6', '\xBB',  /* එ ඔ ඝ ජ ට ථ ධ ර */
+    '\0',
+    '\xE0', '\xB6', '\xAF', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\x8B', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x96', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xB6', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xAF', '\xE0', '\xB7', '\x94',  /* ද ඳ උ ල තූ තු බු දු */
+    '\0',
+    '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x92', ' ', '\xE0', '\xAE', '\x93', ' ', '\xE0', '\xAE', '\xB1', ' ', '\xE0', '\xAE', '\x88', ' ', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9A',  /* உ ஒ ஓ ற ஈ க ங ச */
+    '\0',
+    '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x9A', ' ', '\xE0', '\xAE', '\xB2', ' ', '\xE0', '\xAE', '\xB6', ' ', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9F', ' ', '\xE0', '\xAE', '\xAA',  /* க ச ல ஶ உ ங ட ப */
+    '\0',
+    '\xE0', '\xB0', '\x87', ' ', '\xE0', '\xB0', '\x8C', ' ', '\xE0', '\xB0', '\x99', ' ', '\xE0', '\xB0', '\x9E', ' ', '\xE0', '\xB0', '\xA3', ' ', '\xE0', '\xB0', '\xB1', ' ', '\xE0', '\xB1', '\xAF',  /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
+    '\0',
+    '\xE0', '\xB0', '\x85', ' ', '\xE0', '\xB0', '\x95', ' ', '\xE0', '\xB0', '\x9A', ' ', '\xE0', '\xB0', '\xB0', ' ', '\xE0', '\xB0', '\xBD', ' ', '\xE0', '\xB1', '\xA8', ' ', '\xE0', '\xB1', '\xAC',  /* అ క చ ర ఽ ౨ ౬ */
+    '\0',
+    '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB9', '\x80', ' ', '\xE0', '\xB9', '\x81', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\x81', ' ', '\xE0', '\xB8', '\xB2',  /* บ เ แ อ ก า */
+    '\0',
+    '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\xA9', ' ', '\xE0', '\xB8', '\xAF', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\xA2', ' ', '\xE0', '\xB8', '\xAE',  /* บ ป ษ ฯ อ ย ฮ */
+    '\0',
+    '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\x9D', ' ', '\xE0', '\xB8', '\x9F',  /* ป ฝ ฟ */
+    '\0',
+    '\xE0', '\xB9', '\x82', ' ', '\xE0', '\xB9', '\x83', ' ', '\xE0', '\xB9', '\x84',  /* โ ใ ไ */
+    '\0',
+    '\xE0', '\xB8', '\x8E', ' ', '\xE0', '\xB8', '\x8F', ' ', '\xE0', '\xB8', '\xA4', ' ', '\xE0', '\xB8', '\xA6',  /* ฎ ฏ ฤ ฦ */
+    '\0',
+    '\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90',  /* ญ ฐ */
+    '\0',
+    '\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93',  /* ๐ ๑ ๓ */
 #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', '|',  /* 齊 | */
-    '\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',  /* 顾 */
+    '\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', ' ', '|',  /*  齊 | */
+    ' ', '\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', '|',  /* 说 | */
-    '\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',  /* 面 */
+    '\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', ' ', '|',  /*  说 | */
+    ' ', '\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', '|',  /* 通 | */
-    '\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',  /* 隨 */
+    ' ', '\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', ' ', '|',  /*  通 | */
+    ' ', '\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', '|',  /* 起 | */
-    '\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',  /* 间 */
+    '\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', ' ', '|',  /*  起 | */
+    ' ', '\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',
@@ -117,6 +281,33 @@
   af_blue_stringsets[] =
   {
     /* */
+    { AF_BLUE_STRING_ARABIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     },
+    { AF_BLUE_STRING_ARABIC_BOTTOM, 0                              },
+    { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL },
+    { AF_BLUE_STRING_MAX,           0                              },
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                      0                                 },
+    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_BENGALI_BASE, 0                                 },
+    { AF_BLUE_STRING_MAX,          0                                 },
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 },
+    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 },
+    { AF_BLUE_STRING_CHEROKEE_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      |
@@ -132,6 +323,23 @@
     { AF_BLUE_STRING_DEVANAGARI_BASE,   0                                 },
     { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 },
     { AF_BLUE_STRING_MAX,               0                                 },
+    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,             0                          },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                          0                                 },
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_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        },
@@ -140,11 +348,47 @@
     { AF_BLUE_STRING_GREEK_SMALL,           0                                 },
     { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 },
     { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_MAX,                0                                 },
+    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { 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                             },
+    { AF_BLUE_STRING_KANNADA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_KANNADA_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,            0                          },
+    { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    },
+    { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 },
+    { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 },
+    { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0                                 },
+    { AF_BLUE_STRING_MAX,                         0                                 },
+    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 },
+    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 },
+    { AF_BLUE_STRING_MAX,                0                                 },
     { 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        },
@@ -153,6 +397,51 @@
     { AF_BLUE_STRING_LATIN_SMALL,           0                                 },
     { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 },
     { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           0                                 },
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                        0                                 },
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           0                                 },
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                        0                                 },
+    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,              0                          },
+    { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_MYANMAR_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_MYANMAR_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,               0                                 },
+    { AF_BLUE_STRING_MAX, 0 },
+    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          },
+    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          },
+    { AF_BLUE_STRING_MAX,               0                          },
+    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,          0                          },
+    { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,           0                          },
+    { AF_BLUE_STRING_THAI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_THAI_BOTTOM,          0                                 },
+    { AF_BLUE_STRING_THAI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_THAI_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_THAI_DESCENDER,       0                                 },
+    { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_THAI_DIGIT_TOP,       0                                 },
+    { AF_BLUE_STRING_MAX,                  0                                 },
 #ifdef AF_CONFIG_OPTION_CJK
     { AF_BLUE_STRING_CJK_TOP,    AF_BLUE_PROPERTY_CJK_TOP     },
     { AF_BLUE_STRING_CJK_BOTTOM, 0                            },
diff --git a/src/autofit/afblue.cin b/src/autofit/afblue.cin
index c6762be..0c3cae8 100644
--- a/src/autofit/afblue.cin
+++ b/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter data for blue strings (body).                            */
 /*                                                                         */
-/*  Copyright 2013 by                                                      */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
index 74a472d..f5f04f2 100644
--- a/src/autofit/afblue.dat
+++ b/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
 //
 //    Auto-fitter data for blue strings.
 //
-//  Copyright 2013, 2014 by
+//  Copyright 2013-2016 by
 //  David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 //  This file is part of the FreeType project, and may only be used,
@@ -20,9 +20,8 @@
 // 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).
+// `maximum' template.  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
@@ -30,15 +29,20 @@
 //
 // 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.  Space characters within the string are ignored too.  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.
+// - A string of characters or character clusters (for example, representing
+//   Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
+//   quotes, using C syntax, where the elements are separated by spaces.
+//   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.
+//
+//   For strings, the `maximum' template holds the maximum number of
+//   non-space characters in all 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
@@ -47,6 +51,9 @@
 //   character after each block and counts the number of blocks to set the
 //   enumeration values.
 //
+//   For data blocks, the `maximum' template holds the maximum number of
+//   array elements.
+//
 // A section can contain either strings only or data blocks only.
 //
 // A comment line starts with `//'; it gets removed.  A preprocessor
@@ -58,8 +65,8 @@
 // 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
+// data, this isn't a problem.  Note 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.
 
 
@@ -67,17 +74,56 @@
 
 AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
 
-  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_ARABIC_TOP
+    "ا إ ل ك ط ظ"
+  AF_BLUE_STRING_ARABIC_BOTTOM
+    "ت ث ط ظ ك"
+  // We don't necessarily have access to medial forms via Unicode in case
+  // Arabic presentational forms are missing.  The only character that is
+  // guaranteed to have the same vertical position with joining (this is,
+  // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
+  // round and flat curves.
+  AF_BLUE_STRING_ARABIC_JOIN
+    "ـ"
 
-  // we separate the letters with spaces to avoid ligatures;
-  // this is just for convenience to simplify reading
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP
+    "Ա Մ Ւ Ս Բ Գ Դ Օ"
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM
+    "Ւ Ո Դ Ճ Շ Ս Տ Օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER
+    "ե է ի մ վ ֆ ճ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_TOP
+    "ա յ ւ ս գ շ ր օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM
+    "հ ո ճ ա ե ծ ս օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER
+    "բ ը ի լ ղ պ փ ց"
+
+  AF_BLUE_STRING_BENGALI_BASE
+    "অ ড ত ন ব ভ ল ক"
+  AF_BLUE_STRING_BENGALI_TOP
+    "ই ট ঠ ি ী ৈ ৗ"
+  AF_BLUE_STRING_BENGALI_HEAD
+    "ও এ ড ত ন ব ল ক"
+
+  AF_BLUE_STRING_CHEROKEE_CAPITAL
+    "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ"
+  AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER
+    "ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ"
+  AF_BLUE_STRING_CHEROKEE_SMALL
+    "ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ"
+  AF_BLUE_STRING_CHEROKEE_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_DEVANAGARI_BASE
     "क म अ आ थ ध भ श"
   AF_BLUE_STRING_DEVANAGARI_TOP
@@ -90,76 +136,230 @@
   AF_BLUE_STRING_DEVANAGARI_BOTTOM
     "ु ृ"
 
+  AF_BLUE_STRING_ETHIOPIC_TOP
+    "ሀ ሃ ዘ ፐ ማ በ ዋ ዐ"
+  AF_BLUE_STRING_ETHIOPIC_BOTTOM
+    "ለ ሐ በ ዘ ሀ ሪ ዐ ጨ"
+
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP
+    "გ დ ე ვ თ ი ო ღ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM
+    "ა ზ მ ს შ ძ ხ პ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER
+    "ს ხ ქ ზ მ შ ჩ წ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER
+    "ე ვ ჟ ტ უ ფ ქ ყ"
+
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP
+    "Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ"
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM
+    "Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ"
+
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP
+    "ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM
+    "ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER
+    "ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
+    "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ"
+
   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_GUJARATI_TOP
+    "ત ન ઋ ઌ છ ટ ર ૦"
+  AF_BLUE_STRING_GUJARATI_BOTTOM
+    "ખ ગ ઘ ઞ ઇ ઈ ઠ જ"
+  AF_BLUE_STRING_GUJARATI_ASCENDER
+    "ઈ ઊ િ ી લી શ્ચિ જિ સી"
+  AF_BLUE_STRING_GUJARATI_DESCENDER
+    "ુ ૃ ૄ ખુ છૃ છૄ"
+  AF_BLUE_STRING_GUJARATI_DIGIT_TOP
+    "૦ ૧ ૨ ૩ ૭"
+
+  AF_BLUE_STRING_GURMUKHI_BASE
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_HEAD
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_TOP
+    "ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ"
+  AF_BLUE_STRING_GURMUKHI_BOTTOM
+    "ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ"
+  AF_BLUE_STRING_GURMUKHI_DIGIT_TOP
+    "੦ ੧ ੨ ੩ ੭"
 
   AF_BLUE_STRING_HEBREW_TOP
-    "בדהחךכםס"
+    "ב ד ה ח ך כ ם ס"
   AF_BLUE_STRING_HEBREW_BOTTOM
-    "בטכםסצ"
+    "ב ט כ ם ס צ"
   AF_BLUE_STRING_HEBREW_DESCENDER
-    "קךןףץ"
+    "ק ך ן ף ץ"
+
+  AF_BLUE_STRING_KANNADA_TOP
+    "ಇ ಊ ಐ ಣ ಸಾ ನಾ ದಾ ರಾ"
+  AF_BLUE_STRING_KANNADA_BOTTOM
+    "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭"
+
+  AF_BLUE_STRING_KHMER_TOP
+    "ខ ទ ន ឧ ឩ ា"
+  AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
+    "ក្ក ក្ខ ក្គ ក្ថ"
+  AF_BLUE_STRING_KHMER_BOTTOM
+    "ខ ឃ ច ឋ ប ម យ ឲ"
+  AF_BLUE_STRING_KHMER_DESCENDER
+    "ត្រ រៀ ឲ្យ អឿ"
+  AF_BLUE_STRING_KHMER_LARGE_DESCENDER
+    "ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ"
+
+  AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
+    "᧠ ᧡"
+  AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
+    "᧶ ᧹"
+
+  AF_BLUE_STRING_LAO_TOP
+    "າ ດ ອ ມ ລ ວ ຣ ງ"
+  AF_BLUE_STRING_LAO_BOTTOM
+    "າ ອ ບ ຍ ຣ ຮ ວ ຢ"
+  AF_BLUE_STRING_LAO_ASCENDER
+    "ປ ຢ ຟ ຝ"
+  AF_BLUE_STRING_LAO_LARGE_ASCENDER
+    "ໂ ໄ ໃ"
+  AF_BLUE_STRING_LAO_DESCENDER
+    "ງ ຊ ຖ ຽ ໆ ຯ"
 
   AF_BLUE_STRING_LATIN_CAPITAL_TOP
-    "THEZOCQS"
+    "T H E Z O C Q S"
   AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
-    "HEZLOCUS"
+    "H E Z L O C U S"
   AF_BLUE_STRING_LATIN_SMALL_F_TOP
-    "fijkdbh"
+    "f i j k d b h"
   AF_BLUE_STRING_LATIN_SMALL
-    "xzroesc"
+    "x z r o e s c"
   AF_BLUE_STRING_LATIN_SMALL_DESCENDER
-    "pqgjy"
+    "p q g j y"
+
+  // we assume that both the subscript and superscript ranges
+  // don't contain oldstyle digits (actually, most fonts probably
+  // have digits only in those ranges)
+  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
+    "₀ ₃ ₅ ₇ ₈"
+  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
+    "₀ ₁ ₂ ₃ ₈"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
+    "ᵢ ⱼ ₕ ₖ ₗ"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL
+    "ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
+    "ᵦ ᵧ ᵨ ᵩ ₚ"
+
+  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
+    "⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ"
+  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
+    "⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
+    "ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL
+    "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
+    "ᵖ ʸ ᵍ"
+
+  AF_BLUE_STRING_MALAYALAM_TOP
+    "ഒ ട ഠ റ ച പ ച്ച പ്പ"
+  AF_BLUE_STRING_MALAYALAM_BOTTOM
+    "ട ഠ ധ ശ ഘ ച ഥ ല"
+
+  AF_BLUE_STRING_MYANMAR_TOP
+    "ခ ဂ င ဒ ဝ ၥ ၊ ။"
+  AF_BLUE_STRING_MYANMAR_BOTTOM
+    "င ဎ ဒ ပ ဗ ဝ ၊ ။"
+  AF_BLUE_STRING_MYANMAR_ASCENDER
+    "ဩ ြ ၍ ၏ ၆ ါ ိ"
+  AF_BLUE_STRING_MYANMAR_DESCENDER
+    "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
+
+  AF_BLUE_STRING_SINHALA_TOP
+    "ඉ ක ඝ ඳ ප ය ල ෆ"
+  AF_BLUE_STRING_SINHALA_BOTTOM
+    "එ ඔ ඝ ජ ට ථ ධ ර"
+  AF_BLUE_STRING_SINHALA_DESCENDER
+    "ද ඳ උ ල තූ තු බු දු"
+
+  AF_BLUE_STRING_TAMIL_TOP
+    "உ ஒ ஓ ற ஈ க ங ச"
+  AF_BLUE_STRING_TAMIL_BOTTOM
+    "க ச ல ஶ உ ங ட ப"
+
+  AF_BLUE_STRING_TELUGU_TOP
+    "ఇ ఌ ఙ ఞ ణ ఱ ౯"
+  AF_BLUE_STRING_TELUGU_BOTTOM
+    "అ క చ ర ఽ ౨ ౬"
+
+  AF_BLUE_STRING_THAI_TOP
+    "บ เ แ อ ก า"
+  AF_BLUE_STRING_THAI_BOTTOM
+    "บ ป ษ ฯ อ ย ฮ"
+  AF_BLUE_STRING_THAI_ASCENDER
+    "ป ฝ ฟ"
+  AF_BLUE_STRING_THAI_LARGE_ASCENDER
+    "โ ใ ไ"
+  AF_BLUE_STRING_THAI_DESCENDER
+    "ฎ ฏ ฤ ฦ"
+  AF_BLUE_STRING_THAI_LARGE_DESCENDER
+    "ญ ฐ"
+  AF_BLUE_STRING_THAI_DIGIT_TOP
+    "๐ ๑ ๓"
+
 
 #ifdef AF_CONFIG_OPTION_CJK
 
   AF_BLUE_STRING_CJK_TOP
-    "他们你來們到和地"
-    "对對就席我时時會"
-    "来為能舰說说这這"
-    "齊 |"
-    "军同已愿既星是景"
-    "民照现現理用置要"
-    "軍那配里開雷露面"
-    "顾"
+    "他 们 你 來 們 到 和 地"
+    " 对 對 就 席 我 时 時 會"
+    " 来 為 能 舰 說 说 这 這"
+    " 齊 |"
+    " 军 同 已 愿 既 星 是 景"
+    " 民 照 现 現 理 用 置 要"
+    " 軍 那 配 里 開 雷 露 面"
+    " 顾"
   AF_BLUE_STRING_CJK_BOTTOM
-    "个为人他以们你來"
-    "個們到和大对對就"
-    "我时時有来為要說"
-    "说 |"
-    "主些因它想意理生"
-    "當看着置者自著裡"
-    "过还进進過道還里"
-    "面"
+    "个 为 人 他 以 们 你 來"
+    " 個 們 到 和 大 对 對 就"
+    " 我 时 時 有 来 為 要 說"
+    " 说 |"
+    " 主 些 因 它 想 意 理 生"
+    " 當 看 着 置 者 自 著 裡"
+    " 过 还 进 進 過 道 還 里"
+    " 面"
 
 #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
 
   AF_BLUE_STRING_CJK_LEFT
-    "些们你來們到和地"
-    "她将將就年得情最"
-    "样樣理能說说这這"
-    "通 |"
-    "即吗吧听呢品响嗎"
-    "师師收断斷明眼間"
-    "间际陈限除陳随際"
-    "隨"
+    " 些 们 你 來 們 到 和 地"
+    " 她 将 將 就 年 得 情 最"
+    " 样 樣 理 能 說 说 这 這"
+    " 通 |"
+    " 即 吗 吧 听 呢 品 响 嗎"
+    " 师 師 收 断 斷 明 眼 間"
+    " 间 际 陈 限 除 陳 随 際"
+    " 隨"
   AF_BLUE_STRING_CJK_RIGHT
-    "事前學将將情想或"
-    "政斯新样樣民沒没"
-    "然特现現球第經谁"
-    "起 |"
-    "例別别制动動吗嗎"
-    "增指明朝期构物确"
-    "种調调費费那都間"
-    "间"
+    "事 前 學 将 將 情 想 或"
+    " 政 斯 新 样 樣 民 沒 没"
+    " 然 特 现 現 球 第 經 谁"
+    " 起 |"
+    " 例 別 别 制 动 動 吗 嗎"
+    " 增 指 明 朝 期 构 物 确"
+    " 种 調 调 費 费 那 都 間"
+    " 间"
 
 #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
 
@@ -191,6 +391,14 @@
 // respectively.  Only horizontal blue zones (i.e., adjusting vertical
 // coordinate values) are supported.
 //
+// Some scripts like Khmer need character composition to get all necessary
+// blue zones, since Unicode only provides an abstract data model that
+// doesn't represent all possible glyph shapes.  For such character
+// clusters, the HarfBuzz library is used to convert them into the
+// corresponding glyphs.  The largest glyph element (where `largest' can be
+// either `largest ascender' or `largest descender') then defines the
+// corresponding flat or round extremum.
+//
 // For the latin auto-hinter, the overshoot should be larger than the
 // reference for top zones, and vice versa for bottom zones.
 //
@@ -201,6 +409,21 @@
 //
 //     If not set, take the minimum values.
 //
+//     Mutually exclusive with `LATIN_SUB_TOP'.
+//
+//   LATIN_SUB_TOP
+//     For all glyphs of a character cluster, compute the maximum flat
+//     and round coordinate values of each component, then take the
+//     smallest of the maximum values.  The idea is to get the top of
+//     subscript glyphs, as used in Khmer, for example.  Note that
+//     this mechanism doesn't work for ordinary ligatures.
+//
+//     This flags indicates a secondary blue zone: It gets removed if
+//     there is a non-LATIN_SUB_TOP blue zone at the same coordinate
+//     value (after scaling).
+//
+//     Mutually exclusive with `LATIN_TOP'.
+//
 //   LATIN_NEUTRAL
 //     Ignore round extrema and define the blue zone with flat values only.
 //     Both top and bottom of contours can match.  This is useful for
@@ -236,11 +459,11 @@
 //
 // Characters in a blue string are *not* automatically classified.  Instead,
 // first come the characters used for the overshoot value, then the
-// character `|', then the characters used for the reference value.  The
-// blue zone is then set up by the mean values of all reference values and
-// all overshoot values, respectively.  Both horizontal and vertical blue
-// zones (i.e., adjusting vertical and horizontal coordinate values,
-// respectively) are supported.
+// character `|', then the characters used for the reference value
+// (everything separated by space characters).  The blue zone is then set up
+// by the mean values of all reference values and all overshoot values,
+// respectively.  Both horizontal and vertical blue zones (i.e., adjusting
+// vertical and horizontal coordinate values, respectively) are supported.
 //
 // For the cjk auto-hinter, the overshoot should be smaller than the
 // reference for top zones, and vice versa for bottom zones.
@@ -260,6 +483,41 @@
 
 AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
 
+  AF_BLUE_STRINGSET_ARAB
+    { AF_BLUE_STRING_ARABIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     }
+    { AF_BLUE_STRING_ARABIC_BOTTOM, 0                              }
+    { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+    { AF_BLUE_STRING_MAX,           0                              }
+
+  AF_BLUE_STRINGSET_ARMN
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_BENG
+    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_BENGALI_BASE, 0                                 }
+    { AF_BLUE_STRING_MAX,          0                                 }
+
+  AF_BLUE_STRINGSET_CHER
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 }
+    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 }
+    { AF_BLUE_STRING_CHEROKEE_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                                 }
@@ -279,6 +537,30 @@
     { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 }
     { AF_BLUE_STRING_MAX,               0                                 }
 
+  AF_BLUE_STRINGSET_ETHI
+    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,             0                          }
+
+  // blue zones for Mtavruli are missing (not yet defined in Unicode)
+  AF_BLUE_STRINGSET_GEOR
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                          0                                 }
+
+  AF_BLUE_STRINGSET_GEOK
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_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                                 }
@@ -289,6 +571,25 @@
     { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 }
     { AF_BLUE_STRING_MAX,                   0                                 }
 
+  AF_BLUE_STRINGSET_GUJR
+    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
+  AF_BLUE_STRINGSET_GURU
+    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
   AF_BLUE_STRINGSET_HEBR
     { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
                                        AF_BLUE_PROPERTY_LATIN_LONG   }
@@ -296,6 +597,35 @@
     { AF_BLUE_STRING_HEBREW_DESCENDER, 0                             }
     { AF_BLUE_STRING_MAX,              0                             }
 
+  AF_BLUE_STRINGSET_KNDA
+    { AF_BLUE_STRING_KANNADA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_KANNADA_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,            0                          }
+
+  AF_BLUE_STRINGSET_KHMR
+    { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    }
+    { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 }
+    { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 }
+    { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_KHMS
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,                         0                                 }
+
+  AF_BLUE_STRINGSET_LAO
+    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 }
+    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
   AF_BLUE_STRINGSET_LATN
     { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
     { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 }
@@ -306,6 +636,70 @@
     { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 }
     { AF_BLUE_STRING_MAX,                   0                                 }
 
+  AF_BLUE_STRINGSET_LATB
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           0                                 }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                        0                                 }
+
+  AF_BLUE_STRINGSET_LATP
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           0                                 }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                        0                                 }
+
+  AF_BLUE_STRINGSET_MLYM
+    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,              0                          }
+
+  AF_BLUE_STRINGSET_MYMR
+    { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_MYANMAR_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_MYANMAR_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,               0                                 }
+
+  AF_BLUE_STRINGSET_NONE
+    { AF_BLUE_STRING_MAX, 0 }
+
+  AF_BLUE_STRINGSET_SINH
+    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          }
+    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          }
+    { AF_BLUE_STRING_MAX,               0                          }
+
+  AF_BLUE_STRINGSET_TAML
+    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,          0                          }
+
+  AF_BLUE_STRINGSET_TELU
+    { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,           0                          }
+
+  AF_BLUE_STRINGSET_THAI
+    { AF_BLUE_STRING_THAI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_THAI_BOTTOM,          0                                 }
+    { AF_BLUE_STRING_THAI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_THAI_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_THAI_DESCENDER,       0                                 }
+    { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_THAI_DIGIT_TOP,       0                                 }
+    { AF_BLUE_STRING_MAX,                  0                                 }
+
+
 #ifdef AF_CONFIG_OPTION_CJK
 
   AF_BLUE_STRINGSET_HANI
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
index d239e8e..75c3ab5 100644
--- a/src/autofit/afblue.h
+++ b/src/autofit/afblue.h
@@ -7,7 +7,7 @@
 /*                                                                         */
 /*    Auto-fitter data for blue strings (specification).                   */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,8 +19,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFBLUE_H__
-#define __AFBLUE_H__
+#ifndef AFBLUE_H_
+#define AFBLUE_H_
 
 
 FT_BEGIN_HEADER
@@ -28,32 +28,35 @@
 
   /* 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 ); \
-          }
+#define GET_UTF8_CHAR( ch, p )                      \
+          do                                        \
+          {                                         \
+            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 ); \
+            }                                       \
+          } while ( 0 )
 
 
   /*************************************************************************/
@@ -74,36 +77,118 @@
 
   typedef enum  AF_Blue_String_
   {
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 0,
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 17,
-    AF_BLUE_STRING_CYRILLIC_SMALL = 34,
-    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 51,
-    AF_BLUE_STRING_DEVANAGARI_BASE = 58,
-    AF_BLUE_STRING_DEVANAGARI_TOP = 83,
-    AF_BLUE_STRING_DEVANAGARI_HEAD = 108,
-    AF_BLUE_STRING_DEVANAGARI_BOTTOM = 133,
-    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 140,
-    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 155,
-    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 168,
-    AF_BLUE_STRING_GREEK_SMALL = 181,
-    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 198,
-    AF_BLUE_STRING_HEBREW_TOP = 215,
-    AF_BLUE_STRING_HEBREW_BOTTOM = 232,
-    AF_BLUE_STRING_HEBREW_DESCENDER = 245,
-    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 256,
-    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 265,
-    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 274,
-    AF_BLUE_STRING_LATIN_SMALL = 282,
-    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 290,
-    af_blue_1_1 = 295,
+    AF_BLUE_STRING_ARABIC_TOP = 0,
+    AF_BLUE_STRING_ARABIC_BOTTOM = 18,
+    AF_BLUE_STRING_ARABIC_JOIN = 33,
+    AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 36,
+    AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 60,
+    AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 84,
+    AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 105,
+    AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 129,
+    AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 153,
+    AF_BLUE_STRING_BENGALI_BASE = 177,
+    AF_BLUE_STRING_BENGALI_TOP = 209,
+    AF_BLUE_STRING_BENGALI_HEAD = 237,
+    AF_BLUE_STRING_CHEROKEE_CAPITAL = 269,
+    AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 301,
+    AF_BLUE_STRING_CHEROKEE_SMALL = 333,
+    AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 365,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 381,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 405,
+    AF_BLUE_STRING_CYRILLIC_SMALL = 429,
+    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 453,
+    AF_BLUE_STRING_DEVANAGARI_BASE = 462,
+    AF_BLUE_STRING_DEVANAGARI_TOP = 494,
+    AF_BLUE_STRING_DEVANAGARI_HEAD = 526,
+    AF_BLUE_STRING_DEVANAGARI_BOTTOM = 558,
+    AF_BLUE_STRING_ETHIOPIC_TOP = 566,
+    AF_BLUE_STRING_ETHIOPIC_BOTTOM = 598,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 630,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 662,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 694,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 726,
+    AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 758,
+    AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 790,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 822,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 854,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 886,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 918,
+    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 950,
+    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 971,
+    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 989,
+    AF_BLUE_STRING_GREEK_SMALL = 1007,
+    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 1031,
+    AF_BLUE_STRING_GUJARATI_TOP = 1055,
+    AF_BLUE_STRING_GUJARATI_BOTTOM = 1087,
+    AF_BLUE_STRING_GUJARATI_ASCENDER = 1119,
+    AF_BLUE_STRING_GUJARATI_DESCENDER = 1169,
+    AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 1202,
+    AF_BLUE_STRING_GURMUKHI_BASE = 1222,
+    AF_BLUE_STRING_GURMUKHI_HEAD = 1254,
+    AF_BLUE_STRING_GURMUKHI_TOP = 1286,
+    AF_BLUE_STRING_GURMUKHI_BOTTOM = 1318,
+    AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 1350,
+    AF_BLUE_STRING_HEBREW_TOP = 1370,
+    AF_BLUE_STRING_HEBREW_BOTTOM = 1394,
+    AF_BLUE_STRING_HEBREW_DESCENDER = 1412,
+    AF_BLUE_STRING_KANNADA_TOP = 1427,
+    AF_BLUE_STRING_KANNADA_BOTTOM = 1471,
+    AF_BLUE_STRING_KHMER_TOP = 1503,
+    AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 1527,
+    AF_BLUE_STRING_KHMER_BOTTOM = 1567,
+    AF_BLUE_STRING_KHMER_DESCENDER = 1599,
+    AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 1633,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 1720,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 1728,
+    AF_BLUE_STRING_LAO_TOP = 1736,
+    AF_BLUE_STRING_LAO_BOTTOM = 1768,
+    AF_BLUE_STRING_LAO_ASCENDER = 1800,
+    AF_BLUE_STRING_LAO_LARGE_ASCENDER = 1816,
+    AF_BLUE_STRING_LAO_DESCENDER = 1828,
+    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 1852,
+    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 1868,
+    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 1884,
+    AF_BLUE_STRING_LATIN_SMALL = 1898,
+    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 1912,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 1922,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 1942,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 1962,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL = 1982,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 2018,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 2038,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 2069,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 2098,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL = 2124,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 2149,
+    AF_BLUE_STRING_MALAYALAM_TOP = 2160,
+    AF_BLUE_STRING_MALAYALAM_BOTTOM = 2204,
+    AF_BLUE_STRING_MYANMAR_TOP = 2236,
+    AF_BLUE_STRING_MYANMAR_BOTTOM = 2268,
+    AF_BLUE_STRING_MYANMAR_ASCENDER = 2300,
+    AF_BLUE_STRING_MYANMAR_DESCENDER = 2328,
+    AF_BLUE_STRING_SINHALA_TOP = 2360,
+    AF_BLUE_STRING_SINHALA_BOTTOM = 2392,
+    AF_BLUE_STRING_SINHALA_DESCENDER = 2424,
+    AF_BLUE_STRING_TAMIL_TOP = 2468,
+    AF_BLUE_STRING_TAMIL_BOTTOM = 2500,
+    AF_BLUE_STRING_TELUGU_TOP = 2532,
+    AF_BLUE_STRING_TELUGU_BOTTOM = 2560,
+    AF_BLUE_STRING_THAI_TOP = 2588,
+    AF_BLUE_STRING_THAI_BOTTOM = 2612,
+    AF_BLUE_STRING_THAI_ASCENDER = 2640,
+    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 2652,
+    AF_BLUE_STRING_THAI_DESCENDER = 2664,
+    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 2680,
+    AF_BLUE_STRING_THAI_DIGIT_TOP = 2688,
+    af_blue_1_1 = 2699,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
-    AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 153,
-    af_blue_1_1_1 = af_blue_1_1 + 304,
+    AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
+    af_blue_1_1_1 = af_blue_1_1 + 404,
 #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
     AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1,
-    AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 153,
-    af_blue_1_1_2 = af_blue_1_1_1 + 304,
+    AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 204,
+    af_blue_1_1_2 = af_blue_1_1_1 + 405,
 #else
     af_blue_1_1_2 = af_blue_1_1_1 + 0,
 #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
@@ -136,29 +221,52 @@
   /* 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 )   /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1 << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1 << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1 << 3 )
+#define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP   ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 4 )
 
-#define AF_BLUE_PROPERTY_CJK_TOP    ( 1 << 0 )        /* must have value 1 */
-#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1 << 1 )        /* must have value 2 */
+#define AF_BLUE_PROPERTY_CJK_TOP    ( 1U << 0 )       /* must have value 1 */
+#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
 #define AF_BLUE_PROPERTY_CJK_RIGHT  AF_BLUE_PROPERTY_CJK_TOP
 
 
-#define AF_BLUE_STRINGSET_MAX_LEN  7
+#define AF_BLUE_STRINGSET_MAX_LEN  8
 
   /* The AF_Blue_Stringset enumeration values are offsets into the */
   /* `af_blue_stringsets' array.                                   */
 
   typedef enum  AF_Blue_Stringset_
   {
-    AF_BLUE_STRINGSET_CYRL = 0,
-    AF_BLUE_STRINGSET_DEVA = 6,
-    AF_BLUE_STRINGSET_GREK = 12,
-    AF_BLUE_STRINGSET_HEBR = 19,
-    AF_BLUE_STRINGSET_LATN = 23,
-    af_blue_2_1 = 30,
+    AF_BLUE_STRINGSET_ARAB = 0,
+    AF_BLUE_STRINGSET_ARMN = 4,
+    AF_BLUE_STRINGSET_BENG = 11,
+    AF_BLUE_STRINGSET_CHER = 16,
+    AF_BLUE_STRINGSET_CYRL = 23,
+    AF_BLUE_STRINGSET_DEVA = 29,
+    AF_BLUE_STRINGSET_ETHI = 35,
+    AF_BLUE_STRINGSET_GEOR = 38,
+    AF_BLUE_STRINGSET_GEOK = 43,
+    AF_BLUE_STRINGSET_GREK = 50,
+    AF_BLUE_STRINGSET_GUJR = 57,
+    AF_BLUE_STRINGSET_GURU = 63,
+    AF_BLUE_STRINGSET_HEBR = 69,
+    AF_BLUE_STRINGSET_KNDA = 73,
+    AF_BLUE_STRINGSET_KHMR = 76,
+    AF_BLUE_STRINGSET_KHMS = 82,
+    AF_BLUE_STRINGSET_LAO = 85,
+    AF_BLUE_STRINGSET_LATN = 91,
+    AF_BLUE_STRINGSET_LATB = 98,
+    AF_BLUE_STRINGSET_LATP = 105,
+    AF_BLUE_STRINGSET_MLYM = 112,
+    AF_BLUE_STRINGSET_MYMR = 115,
+    AF_BLUE_STRINGSET_NONE = 120,
+    AF_BLUE_STRINGSET_SINH = 121,
+    AF_BLUE_STRINGSET_TAML = 125,
+    AF_BLUE_STRINGSET_TELU = 128,
+    AF_BLUE_STRINGSET_THAI = 131,
+    af_blue_2_1 = 139,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
     af_blue_2_1_1 = af_blue_2_1 + 2,
@@ -194,7 +302,7 @@
 FT_END_HEADER
 
 
-#endif /* __AFBLUE_H__ */
+#endif /* AFBLUE_H_ */
 
 
 /* END */
diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin
index 0b4b48d..dd44e77 100644
--- a/src/autofit/afblue.hin
+++ b/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter data for blue strings (specification).                   */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFBLUE_H__
-#define __AFBLUE_H__
+#ifndef AFBLUE_H_
+#define AFBLUE_H_
 
 
 FT_BEGIN_HEADER
@@ -25,32 +25,35 @@
 
   /* 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 ); \
-          }
+#define GET_UTF8_CHAR( ch, p )                      \
+          do                                        \
+          {                                         \
+            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 ); \
+            }                                       \
+          } while ( 0 )
 
 
   /*************************************************************************/
@@ -96,13 +99,14 @@
   /* 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 )   /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1 << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1 << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1 << 3 )
+#define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP   ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 4 )
 
-#define AF_BLUE_PROPERTY_CJK_TOP    ( 1 << 0 )        /* must have value 1 */
-#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1 << 1 )        /* must have value 2 */
+#define AF_BLUE_PROPERTY_CJK_TOP    ( 1U << 0 )       /* must have value 1 */
+#define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
 #define AF_BLUE_PROPERTY_CJK_RIGHT  AF_BLUE_PROPERTY_CJK_TOP
 
 
@@ -136,7 +140,7 @@
 FT_END_HEADER
 
 
-#endif /* __AFBLUE_H__ */
+#endif /* AFBLUE_H_ */
 
 
 /* END */
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index ca7acca..4823c1d 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK writing system (body).          */
 /*                                                                         */
-/*  Copyright 2006-2014 by                                                 */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -88,7 +88,6 @@
     {
       FT_Error          error;
       FT_ULong          glyph_index;
-      FT_Long           y_offset;
       int               dim;
       AF_CJKMetricsRec  dummy[1];
       AF_Scaler         scaler = &dummy->root.scaler;
@@ -101,45 +100,61 @@
       AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
                                        [style_class->script];
 
-      FT_UInt32  standard_char;
+      void*        shaper_buf;
+      const char*  p;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+      FT_ULong  ch = 0;
+#endif
 
-      standard_char = script_class->standard_char1;
-      af_get_char_index( &metrics->root,
-                         standard_char,
-                         &glyph_index,
-                         &y_offset );
-      if ( !glyph_index )
+      p          = script_class->standard_charstring;
+      shaper_buf = af_shaper_buf_create( face );
+
+      /* We check a list of standard characters.  The first match wins. */
+
+      glyph_index = 0;
+      while ( *p )
       {
-        if ( script_class->standard_char2 )
-        {
-          standard_char = script_class->standard_char2;
-          af_get_char_index( &metrics->root,
-                             standard_char,
-                             &glyph_index,
-                             &y_offset );
-          if ( !glyph_index )
-          {
-            if ( script_class->standard_char3 )
-            {
-              standard_char = script_class->standard_char3;
-              af_get_char_index( &metrics->root,
-                                 standard_char,
-                                 &glyph_index,
-                                 &y_offset );
-              if ( !glyph_index )
-                goto Exit;
-            }
-            else
-              goto Exit;
-          }
-        }
-        else
-          goto Exit;
+        unsigned int  num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+#endif
+
+
+        while ( *p == ' ' )
+          p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
+
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
+
+        /* otherwise exit loop if we have a result */
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
+        if ( glyph_index )
+          break;
       }
 
+      af_shaper_buf_destroy( face, shaper_buf );
+
+      if ( !glyph_index )
+        goto Exit;
+
+      if ( !glyph_index )
+        goto Exit;
+
       FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
-                  standard_char, glyph_index ));
+                  ch, glyph_index ));
 
       error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
       if ( error || face->glyph->outline.n_points <= 0 )
@@ -177,6 +192,12 @@
         if ( error )
           goto Exit;
 
+        /*
+         *  We assume that the glyphs selected for the stem width
+         *  computation are `featureless' enough so that the linking
+         *  algorithm works fine without adjustments of its scoring
+         *  function.
+         */
         af_latin_hints_link_segments( hints,
                                       0,
                                       NULL,
@@ -260,8 +281,8 @@
     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_UInt     num_fills;
+    FT_UInt     num_flats;
 
     FT_Bool     fill;
 
@@ -275,6 +296,8 @@
     AF_Blue_Stringset         bss = sc->blue_stringset;
     const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
 
+    void*  shaper_buf;
+
 
     /* we walk over the blue character strings as specified in the   */
     /* style's entry in the `af_blue_stringset' array, computing its */
@@ -284,6 +307,8 @@
                 "==========================\n"
                 "\n" ));
 
+    shaper_buf = af_shaper_buf_create( face );
+
     for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
       const char*  p = &af_blue_strings[bs->string];
@@ -322,26 +347,47 @@
 
       while ( *p )
       {
-        FT_ULong    ch;
         FT_ULong    glyph_index;
-        FT_Long     y_offset;
         FT_Pos      best_pos;       /* same as points.y or points.x, resp. */
         FT_Int      best_point;
         FT_Vector*  points;
 
+        unsigned int  num_idx;
 
-        GET_UTF8_CHAR( ch, p );
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+        FT_ULong     ch;
+#endif
+
+
+        while ( *p == ' ' )
+          p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
 
         /* switch to characters that define flat values */
-        if ( ch == '|' )
+        if ( *p == '|' )
         {
           fill = 0;
           FT_TRACE5(( "  [reference values]\n" ));
+          p++;
           continue;
         }
 
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
+
         /* load the character in the face -- skip unknown or empty ones */
-        af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
         if ( glyph_index == 0 )
         {
           FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
@@ -350,9 +396,9 @@
 
         error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
         outline = face->glyph->outline;
-        if ( error || outline.n_points <= 0 )
+        if ( error || outline.n_points <= 2 )
         {
-          FT_TRACE5(( "  U+%04lX contains no outlines\n", ch ));
+          FT_TRACE5(( "  U+%04lX contains no (usable) outlines\n", ch ));
           continue;
         }
 
@@ -431,7 +477,8 @@
           fills[num_fills++] = best_pos;
         else
           flats[num_flats++] = best_pos;
-      }
+
+      } /* end while loop */
 
       if ( num_flats == 0 && num_fills == 0 )
       {
@@ -498,7 +545,10 @@
       FT_TRACE5(( "    -> reference = %ld\n"
                   "       overshoot = %ld\n",
                   *blue_ref, *blue_shoot ));
-    }
+
+    } /* end for loop */
+
+    af_shaper_buf_destroy( face, shaper_buf );
 
     FT_TRACE5(( "\n" ));
 
@@ -512,27 +562,36 @@
   af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
                                FT_Face        face )
   {
-    FT_UInt   i;
     FT_Bool   started = 0, same_width = 1;
     FT_Fixed  advance, old_advance = 0;
 
+    void*  shaper_buf;
 
-    /* digit `0' is 0x30 in all supported charmaps */
-    for ( i = 0x30; i <= 0x39; i++ )
+    /* in all supported charmaps, digits have character codes 0x30-0x39 */
+    const char   digits[] = "0 1 2 3 4 5 6 7 8 9";
+    const char*  p;
+
+
+    p          = digits;
+    shaper_buf = af_shaper_buf_create( face );
+
+    while ( *p )
     {
-      FT_ULong  glyph_index;
-      FT_Long   y_offset;
+      FT_ULong      glyph_index;
+      unsigned int  num_idx;
 
 
-      af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
-      if ( glyph_index == 0 )
+      /* reject input that maps to more than a single glyph */
+      p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+      if ( num_idx > 1 )
         continue;
 
-      if ( FT_Get_Advance( face, glyph_index,
-                           FT_LOAD_NO_SCALE         |
-                           FT_LOAD_NO_HINTING       |
-                           FT_LOAD_IGNORE_TRANSFORM,
-                           &advance ) )
+      glyph_index = af_shaper_get_elem( &metrics->root,
+                                        shaper_buf,
+                                        0,
+                                        &advance,
+                                        NULL );
+      if ( !glyph_index )
         continue;
 
       if ( started )
@@ -550,6 +609,8 @@
       }
     }
 
+    af_shaper_buf_destroy( face, shaper_buf );
+
     metrics->root.digits_have_same_width = same_width;
   }
 
@@ -688,6 +749,22 @@
   }
 
 
+  /* Extract standard_width from writing system/script specific */
+  /* metrics class.                                             */
+
+  FT_LOCAL_DEF( void )
+  af_cjk_get_standard_widths( AF_CJKMetrics  metrics,
+                              FT_Pos*        stdHW,
+                              FT_Pos*        stdVW )
+  {
+    if ( stdHW )
+      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+    if ( stdVW )
+      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -720,8 +797,8 @@
     {
       AF_Point  pt   = seg->first;
       AF_Point  last = seg->last;
-      AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
-      AF_Flags  f1;
+      FT_UInt   f0   = pt->flags & AF_FLAG_CONTROL;
+      FT_UInt   f1;
 
 
       seg->flags &= ~AF_EDGE_ROUND;
@@ -729,7 +806,7 @@
       for ( ; pt != last; f0 = f1 )
       {
         pt = pt->next;
-        f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
+        f1 = pt->flags & AF_FLAG_CONTROL;
 
         if ( !f0 && !f1 )
           break;
@@ -765,10 +842,6 @@
     /* now compare each segment to the others */
     for ( seg1 = segments; seg1 < segment_limit; seg1++ )
     {
-      /* the fake segments are for metrics hinting only */
-      if ( seg1->first == seg1->last )
-        continue;
-
       if ( seg1->dir != major_dir )
         continue;
 
@@ -867,19 +940,19 @@
 
               if ( link == seg2 )
               {
-                seg->link  = 0;
+                seg->link  = NULL;
                 seg->serif = link1;
               }
               else if ( link == link2 )
               {
-                seg->link  = 0;
+                seg->link  = NULL;
                 seg->serif = seg1;
               }
             }
           }
           else
           {
-            seg1->link = link1->link = 0;
+            seg1->link = link1->link = NULL;
 
             break;
           }
@@ -893,15 +966,12 @@
 
       if ( seg2 )
       {
-        seg2->num_linked++;
         if ( seg2->link != seg1 )
         {
-          seg1->link = 0;
+          seg1->link = NULL;
 
           if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )
             seg1->serif = seg2->link;
-          else
-            seg2->num_linked--;
         }
       }
     }
@@ -1018,7 +1088,7 @@
         /* insert a new edge in the list and */
         /* sort according to the position    */
         error = af_axis_hints_new_edge( axis, seg->pos,
-                                        (AF_Direction)seg->dir,
+                                        (AF_Direction)seg->dir, 0,
                                         memory, &edge );
         if ( error )
           goto Exit;
@@ -1028,10 +1098,11 @@
 
         edge->first    = seg;
         edge->last     = seg;
-        edge->fpos     = seg->pos;
-        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
-        seg->edge_next = seg;
         edge->dir      = seg->dir;
+        edge->fpos     = seg->pos;
+        edge->opos     = FT_MulFix( seg->pos, scale );
+        edge->pos      = edge->opos;
+        seg->edge_next = seg;
       }
       else
       {
@@ -1162,7 +1233,7 @@
         /*      Example: the `c' in cour.pfa at size 13     */
 
         if ( edge->serif && edge->link )
-          edge->serif = 0;
+          edge->serif = NULL;
       }
     }
 
@@ -1193,7 +1264,7 @@
 
   /* Compute all edges which lie within blue zones. */
 
-  FT_LOCAL_DEF( void )
+  static void
   af_cjk_hints_compute_blue_edges( AF_GlyphHints  hints,
                                    AF_CJKMetrics  metrics,
                                    AF_Dimension   dim )
@@ -1304,7 +1375,7 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
+#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
 #endif
@@ -1337,6 +1408,12 @@
 
     scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
 
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    /* get (global) warper flag */
+    if ( !metrics->root.globals->module->warping )
+      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
@@ -1357,13 +1434,13 @@
 
   static FT_Pos
   af_cjk_snap_width( AF_Width  widths,
-                     FT_Int    count,
+                     FT_UInt   count,
                      FT_Pos    width )
   {
-    int     n;
-    FT_Pos  best      = 64 + 32 + 2;
-    FT_Pos  reference = width;
-    FT_Pos  scaled;
+    FT_UInt  n;
+    FT_Pos   best      = 64 + 32 + 2;
+    FT_Pos   reference = width;
+    FT_Pos   scaled;
 
 
     for ( n = 0; n < count; n++ )
@@ -1408,8 +1485,8 @@
   af_cjk_compute_stem_width( AF_GlyphHints  hints,
                              AF_Dimension   dim,
                              FT_Pos         width,
-                             AF_Edge_Flags  base_flags,
-                             AF_Edge_Flags  stem_flags )
+                             FT_UInt        base_flags,
+                             FT_UInt        stem_flags )
   {
     AF_CJKMetrics  metrics  = (AF_CJKMetrics)hints->metrics;
     AF_CJKAxis     axis     = &metrics->axis[dim];
@@ -1448,7 +1525,7 @@
       }
 
       if ( dist < 54 )
-        dist += ( 54 - dist ) / 2 ;
+        dist += ( 54 - dist ) / 2;
       else if ( dist < 3 * 64 )
       {
         FT_Pos  delta;
@@ -1533,10 +1610,9 @@
   {
     FT_Pos  dist = stem_edge->opos - base_edge->opos;
 
-    FT_Pos  fitted_width = af_cjk_compute_stem_width(
-                             hints, dim, dist,
-                             (AF_Edge_Flags)base_edge->flags,
-                             (AF_Edge_Flags)stem_edge->flags );
+    FT_Pos  fitted_width = af_cjk_compute_stem_width( hints, dim, dist,
+                                                      base_edge->flags,
+                                                      stem_edge->flags );
 
 
     stem_edge->pos = base_edge->pos + fitted_width;
@@ -1614,8 +1690,8 @@
 
     org_len    = edge2->opos - edge->opos;
     cur_len    = af_cjk_compute_stem_width( hints, dim, org_len,
-                                            (AF_Edge_Flags)edge->flags,
-                                            (AF_Edge_Flags)edge2->flags );
+                                            edge->flags,
+                                            edge2->flags );
 
     org_center = ( edge->opos + edge2->opos ) / 2 + anchor;
     cur_pos1   = org_center - cur_len / 2;
@@ -1716,7 +1792,7 @@
     AF_Edge       edge_limit = edges + axis->num_edges;
     FT_PtrDist    n_edges;
     AF_Edge       edge;
-    AF_Edge       anchor   = 0;
+    AF_Edge       anchor   = NULL;
     FT_Pos        delta    = 0;
     FT_Int        skipped  = 0;
     FT_Bool       has_last_stem = FALSE;
@@ -2179,7 +2255,8 @@
   /* Apply the complete hinting algorithm to a CJK glyph. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_cjk_hints_apply( AF_GlyphHints  hints,
+  af_cjk_hints_apply( FT_UInt        glyph_index,
+                      AF_GlyphHints  hints,
                       FT_Outline*    outline,
                       AF_CJKMetrics  metrics )
   {
@@ -2187,6 +2264,7 @@
     int       dim;
 
     FT_UNUSED( metrics );
+    FT_UNUSED( glyph_index );
 
 
     error = af_glyph_hints_reload( hints, outline );
@@ -2194,7 +2272,13 @@
       goto Exit;
 
     /* analyze glyph outline */
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+           AF_HINTS_DO_WARP( hints )                                ) ||
+         AF_HINTS_DO_HORIZONTAL( hints )                              )
+#else
     if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+#endif
     {
       error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
       if ( error )
@@ -2220,8 +2304,9 @@
       {
 
 #ifdef AF_CONFIG_OPTION_USE_WARPER
-        if ( dim == AF_DIMENSION_HORZ                                  &&
-             metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
+        if ( dim == AF_DIMENSION_HORZ                                 &&
+             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+             AF_HINTS_DO_WARP( hints )                                )
         {
           AF_WarperRec  warper;
           FT_Fixed      scale;
@@ -2243,12 +2328,6 @@
       }
     }
 
-#if 0
-    af_glyph_hints_dump_points( hints );
-    af_glyph_hints_dump_segments( hints );
-    af_glyph_hints_dump_edges( hints );
-#endif
-
     af_glyph_hints_save( hints, outline );
 
   Exit:
@@ -2275,6 +2354,7 @@
     (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init,
     (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)af_cjk_get_standard_widths,
 
     (AF_WritingSystem_InitHintsFunc)   af_cjk_hints_init,
     (AF_WritingSystem_ApplyHintsFunc)  af_cjk_hints_apply
@@ -2294,6 +2374,7 @@
     (AF_WritingSystem_InitMetricsFunc) NULL,
     (AF_WritingSystem_ScaleMetricsFunc)NULL,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)NULL,
 
     (AF_WritingSystem_InitHintsFunc)   NULL,
     (AF_WritingSystem_ApplyHintsFunc)  NULL
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index 4dd4f39..40d1184 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK writing system (specification). */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2011-2014 by                                     */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFCJK_H__
-#define __AFCJK_H__
+#ifndef AFCJK_H_
+#define AFCJK_H_
 
 #include "afhints.h"
 #include "aflatin.h"
@@ -55,14 +55,10 @@
 #define AF_CJK_MAX_WIDTHS  16
 
 
-  enum
-  {
-    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
-  };
+#define AF_CJK_BLUE_ACTIVE      ( 1U << 0 ) /* zone height is <= 3/4px      */
+#define AF_CJK_BLUE_TOP         ( 1U << 1 ) /* result of AF_CJK_IS_TOP_BLUE */
+#define AF_CJK_BLUE_ADJUSTMENT  ( 1U << 2 ) /* used for scale adjustment    */
+                                            /* optimization                 */
 
 
   typedef struct  AF_CJKBlueRec_
@@ -119,7 +115,8 @@
                      AF_CJKMetrics  metrics );
 
   FT_LOCAL( FT_Error )
-  af_cjk_hints_apply( AF_GlyphHints  hints,
+  af_cjk_hints_apply( FT_UInt        glyph_index,
+                      AF_GlyphHints  hints,
                       FT_Outline*    outline,
                       AF_CJKMetrics  metrics );
 
@@ -138,7 +135,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFCJK_H__ */
+#endif /* AFCJK_H_ */
 
 
 /* END */
diff --git a/src/autofit/afcover.h b/src/autofit/afcover.h
index d5ac969..1c39a70 100644
--- a/src/autofit/afcover.h
+++ b/src/autofit/afcover.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter coverages (specification only).                          */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index f8702a1..f3960c8 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
 /*    Auto-fitter dummy routines to be used if no hinting should be        */
 /*    performed (body).                                                    */
 /*                                                                         */
-/*  Copyright 2003-2005, 2011, 2013 by                                     */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -38,11 +38,14 @@
 
 
   static FT_Error
-  af_dummy_hints_apply( AF_GlyphHints  hints,
+  af_dummy_hints_apply( FT_UInt        glyph_index,
+                        AF_GlyphHints  hints,
                         FT_Outline*    outline )
   {
     FT_Error  error;
 
+    FT_UNUSED( glyph_index );
+
 
     error = af_glyph_hints_reload( hints, outline );
     if ( !error )
@@ -62,6 +65,7 @@
     (AF_WritingSystem_InitMetricsFunc) NULL,
     (AF_WritingSystem_ScaleMetricsFunc)NULL,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)NULL,
 
     (AF_WritingSystem_InitHintsFunc)   af_dummy_hints_init,
     (AF_WritingSystem_ApplyHintsFunc)  af_dummy_hints_apply
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index ad1b0d3..7e58d1a 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, 2013 by                                     */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFDUMMY_H__
-#define __AFDUMMY_H__
+#ifndef AFDUMMY_H_
+#define AFDUMMY_H_
 
 #include "aftypes.h"
 
@@ -34,7 +34,7 @@
 FT_END_HEADER
 
 
-#endif /* __AFDUMMY_H__ */
+#endif /* AFDUMMY_H_ */
 
 
 /* END */
diff --git a/src/autofit/aferrors.h b/src/autofit/aferrors.h
index 50e1a22..53c01f6 100644
--- a/src/autofit/aferrors.h
+++ b/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Autofitter error codes (specification only).                         */
 /*                                                                         */
-/*  Copyright 2005, 2012 by                                                */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,12 +23,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __AFERRORS_H__
-#define __AFERRORS_H__
+#ifndef AFERRORS_H_
+#define AFERRORS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  AF_Err_
@@ -36,6 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __AFERRORS_H__ */
+#endif /* AFERRORS_H_ */
+
 
 /* END */
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index a54c20c..ac6dcaf 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter routines to compute global hinting values (body).        */
 /*                                                                         */
-/*  Copyright 2003-2014 by                                                 */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,7 +18,7 @@
 
 #include "afglobal.h"
 #include "afranges.h"
-#include "hbshim.h"
+#include "afshaper.h"
 #include FT_INTERNAL_DEBUG_H
 
 
@@ -42,12 +42,14 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, H, ss )         \
           AF_DEFINE_SCRIPT_CLASS(           \
             af_ ## s ## _script_class,      \
             AF_SCRIPT_ ## S,                \
             af_ ## s ## _uniranges,         \
-            sc1, sc2, sc3 )
+            af_ ## s ## _nonbase_uniranges, \
+            AF_ ## H,                       \
+            ss )
 
 #include "afscript.h"
 
@@ -82,7 +84,7 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, H, ss )   \
           &af_ ## s ## _script_class,
 
   FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
@@ -135,16 +137,15 @@
     FT_Error    error;
     FT_Face     face        = globals->face;
     FT_CharMap  old_charmap = face->charmap;
-    FT_Byte*    gstyles     = globals->glyph_styles;
+    FT_UShort*  gstyles     = globals->glyph_styles;
     FT_UInt     ss;
     FT_UInt     i;
     FT_UInt     dflt        = ~0U; /* a non-valid value */
 
 
     /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
-    FT_MEM_SET( globals->glyph_styles,
-                AF_STYLE_UNASSIGNED,
-                globals->glyph_count );
+    for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
+      gstyles[i] = AF_STYLE_UNASSIGNED;
 
     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
     if ( error )
@@ -190,10 +191,10 @@
 
           gindex = FT_Get_Char_Index( face, charcode );
 
-          if ( gindex != 0                             &&
-               gindex < (FT_ULong)globals->glyph_count &&
-               gstyles[gindex] == AF_STYLE_UNASSIGNED  )
-            gstyles[gindex] = (FT_Byte)ss;
+          if ( gindex != 0                                                &&
+               gindex < (FT_ULong)globals->glyph_count                    &&
+               ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+            gstyles[gindex] = (FT_UShort)ss;
 
           for (;;)
           {
@@ -202,32 +203,61 @@
             if ( gindex == 0 || charcode > range->last )
               break;
 
-            if ( gindex < (FT_ULong)globals->glyph_count &&
-                 gstyles[gindex] == AF_STYLE_UNASSIGNED  )
-              gstyles[gindex] = (FT_Byte)ss;
+            if ( gindex < (FT_ULong)globals->glyph_count                    &&
+                 ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+              gstyles[gindex] = (FT_UShort)ss;
+          }
+        }
+
+        /* do the same for the script's non-base characters */
+        for ( range = script_class->script_uni_nonbase_ranges;
+              range->first != 0;
+              range++ )
+        {
+          FT_ULong  charcode = range->first;
+          FT_UInt   gindex;
+
+
+          gindex = FT_Get_Char_Index( face, charcode );
+
+          if ( gindex != 0                                          &&
+               gindex < (FT_ULong)globals->glyph_count              &&
+               ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+            gstyles[gindex] |= AF_NONBASE;
+
+          for (;;)
+          {
+            charcode = FT_Get_Next_Char( face, charcode, &gindex );
+
+            if ( gindex == 0 || charcode > range->last )
+              break;
+
+            if ( gindex < (FT_ULong)globals->glyph_count              &&
+                 ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+              gstyles[gindex] |= AF_NONBASE;
           }
         }
       }
       else
       {
         /* get glyphs not directly addressable by cmap */
-        af_get_coverage( globals, style_class, gstyles );
+        af_shaper_get_coverage( globals, style_class, gstyles, 0 );
       }
     }
 
-    /* handle the default OpenType features of the default script ... */
-    af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
-
-    /* ... and the remaining default OpenType features */
+    /* handle the remaining default OpenType features ... */
     for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
     {
       AF_StyleClass  style_class = AF_STYLE_CLASSES_GET[ss];
 
 
-      if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
-        af_get_coverage( globals, style_class, gstyles );
+      if ( style_class->coverage == AF_COVERAGE_DEFAULT )
+        af_shaper_get_coverage( globals, style_class, gstyles, 0 );
     }
 
+    /* ... and finally the default OpenType features of the default script */
+    af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles, 1 );
+
     /* mark ASCII digits */
     for ( i = 0x30; i <= 0x39; i++ )
     {
@@ -250,9 +280,9 @@
 
       for ( nn = 0; nn < globals->glyph_count; nn++ )
       {
-        if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED )
+        if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
         {
-          gstyles[nn] &= ~AF_STYLE_UNASSIGNED;
+          gstyles[nn] &= ~AF_STYLE_MASK;
           gstyles[nn] |= globals->module->fallback_style;
         }
       }
@@ -276,7 +306,7 @@
 
       for ( idx = 0; idx < globals->glyph_count; idx++ )
       {
-        if ( ( gstyles[idx] & ~AF_DIGIT ) == style_class->style )
+        if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
         {
           if ( !( count % 10 ) )
             FT_TRACE4(( " " ));
@@ -314,17 +344,28 @@
 
     memory = face->memory;
 
-    if ( FT_ALLOC( globals, sizeof ( *globals ) +
-                            face->num_glyphs * sizeof ( FT_Byte ) ) )
+    /* we allocate an AF_FaceGlobals structure together */
+    /* with the glyph_styles array                      */
+    if ( FT_ALLOC( globals,
+                   sizeof ( *globals ) +
+                     (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
       goto Exit;
 
-    globals->face         = face;
-    globals->glyph_count  = face->num_glyphs;
-    globals->glyph_styles = (FT_Byte*)( globals + 1 );
-    globals->module       = module;
+    globals->face                      = face;
+    globals->glyph_count               = face->num_glyphs;
+    /* right after the globals structure come the glyph styles */
+    globals->glyph_styles              = (FT_UShort*)( globals + 1 );
+    globals->module                    = module;
+    globals->stem_darkening_for_ppem   = 0;
+    globals->darken_x                  = 0;
+    globals->darken_y                  = 0;
+    globals->standard_vertical_width   = 0;
+    globals->standard_horizontal_width = 0;
+    globals->scale_down_factor         = 0;
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
     globals->hb_font = hb_ft_font_create( face, NULL );
+    globals->hb_buf  = hb_buffer_create();
 #endif
 
     error = af_face_globals_compute_style_coverage( globals );
@@ -371,11 +412,21 @@
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
       hb_font_destroy( globals->hb_font );
       globals->hb_font = NULL;
+
+      hb_buffer_destroy( globals->hb_buf );
+      globals->hb_buf = NULL;
 #endif
 
-      globals->glyph_count  = 0;
-      globals->glyph_styles = NULL;  /* no need to free this one! */
-      globals->face         = NULL;
+      globals->glyph_count               = 0;
+      globals->stem_darkening_for_ppem   = 0;
+      globals->darken_x                  = 0;
+      globals->darken_y                  = 0;
+      globals->standard_vertical_width   = 0;
+      globals->standard_horizontal_width = 0;
+      globals->scale_down_factor         = 0;
+      /* no need to free this one! */
+      globals->glyph_styles              = NULL;
+      globals->face                      = NULL;
 
       FT_FREE( globals );
     }
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 38d8d69..ce6b9e8 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-2014 by                          */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,13 +17,13 @@
 /***************************************************************************/
 
 
-#ifndef __AFGLOBAL_H__
-#define __AFGLOBAL_H__
+#ifndef AFGLOBAL_H_
+#define AFGLOBAL_H_
 
 
 #include "aftypes.h"
 #include "afmodule.h"
-#include "hbshim.h"
+#include "afshaper.h"
 
 
 FT_BEGIN_HEADER
@@ -34,7 +34,7 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 )                    \
+#define SCRIPT( s, S, d, h, H, ss )                            \
           AF_DECLARE_SCRIPT_CLASS( af_ ## s ## _script_class )
 
 #include "afscript.h"
@@ -72,10 +72,16 @@
 #endif
   /* default script for OpenType; ignored if HarfBuzz isn't used */
 #define AF_SCRIPT_DEFAULT    AF_SCRIPT_LATN
-  /* a bit mask indicating an uncovered glyph        */
-#define AF_STYLE_UNASSIGNED  0x7F
-  /* if this flag is set, we have an ASCII digit     */
-#define AF_DIGIT             0x80
+
+  /* a bit mask for AF_DIGIT and AF_NONBASE */
+#define AF_STYLE_MASK        0x3FFF
+  /* an uncovered glyph      */
+#define AF_STYLE_UNASSIGNED  AF_STYLE_MASK
+
+  /* if this flag is set, we have an ASCII digit   */
+#define AF_DIGIT             0x8000U
+  /* if this flag is set, we have a non-base character */
+#define AF_NONBASE           0x4000U
 
   /* `increase-x-height' property */
 #define AF_PROP_INCREASE_X_HEIGHT_MIN  6
@@ -100,10 +106,11 @@
   {
     FT_Face          face;
     FT_Long          glyph_count;    /* same as face->num_glyphs */
-    FT_Byte*         glyph_styles;
+    FT_UShort*       glyph_styles;
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
     hb_font_t*       hb_font;
+    hb_buffer_t*     hb_buf;           /* for feature comparison */
 #endif
 
     /* per-face auto-hinter properties */
@@ -111,6 +118,22 @@
 
     AF_StyleMetrics  metrics[AF_STYLE_MAX];
 
+    /* Compute darkening amount once per size.  Use this to check whether */
+    /* darken_{x,y} needs to be recomputed.                               */
+    FT_UShort        stem_darkening_for_ppem;
+    /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_HORZ] */
+    /* to compute the darkening amount.                       */
+    FT_Pos           standard_vertical_width;
+    /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_VERT] */
+    /* to compute the darkening amount.                       */
+    FT_Pos           standard_horizontal_width;
+    /* The actual amount to darken a glyph along the X axis. */
+    FT_Pos           darken_x;
+    /* The actual amount to darken a glyph along the Y axis. */
+    FT_Pos           darken_y;
+    /* Amount to scale down by to keep emboldened points */
+    /* on the Y-axis in pre-computed blue zones.         */
+    FT_Fixed         scale_down_factor;
     AF_Module        module;         /* to access global properties */
 
   } AF_FaceGlobalsRec;
@@ -144,7 +167,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFGLOBAL_H__ */
+#endif /* AFGLOBAL_H_ */
 
 
 /* END */
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index 88a97d4..0f7f6e5 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (body).                                 */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009-2014 by                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -43,7 +43,15 @@
     AF_Segment  segment = NULL;
 
 
-    if ( axis->num_segments >= axis->max_segments )
+    if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
+    {
+      if ( axis->segments == NULL )
+      {
+        axis->segments     = axis->embedded.segments;
+        axis->max_segments = AF_SEGMENTS_EMBEDDED;
+      }
+    }
+    else if ( axis->num_segments >= axis->max_segments )
     {
       FT_Int  old_max = axis->max_segments;
       FT_Int  new_max = old_max;
@@ -60,8 +68,18 @@
       if ( new_max < old_max || new_max > big_max )
         new_max = big_max;
 
-      if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
-        goto Exit;
+      if ( axis->segments == axis->embedded.segments )
+      {
+        if ( FT_NEW_ARRAY( axis->segments, new_max ) )
+          goto Exit;
+        ft_memcpy( axis->segments, axis->embedded.segments,
+                   sizeof ( axis->embedded.segments ) );
+      }
+      else
+      {
+        if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
+          goto Exit;
+      }
 
       axis->max_segments = new_max;
     }
@@ -74,12 +92,14 @@
   }
 
 
-  /* Get new edge for given axis, direction, and position. */
+  /* Get new edge for given axis, direction, and position, */
+  /* without initializing the edge itself.                 */
 
   FT_LOCAL( FT_Error )
   af_axis_hints_new_edge( AF_AxisHints  axis,
                           FT_Int        fpos,
                           AF_Direction  dir,
+                          FT_Bool       top_to_bottom_hinting,
                           FT_Memory     memory,
                           AF_Edge      *anedge )
   {
@@ -88,7 +108,15 @@
     AF_Edge   edges;
 
 
-    if ( axis->num_edges >= axis->max_edges )
+    if ( axis->num_edges < AF_EDGES_EMBEDDED )
+    {
+      if ( axis->edges == NULL )
+      {
+        axis->edges     = axis->embedded.edges;
+        axis->max_edges = AF_EDGES_EMBEDDED;
+      }
+    }
+    else if ( axis->num_edges >= axis->max_edges )
     {
       FT_Int  old_max = axis->max_edges;
       FT_Int  new_max = old_max;
@@ -105,8 +133,18 @@
       if ( new_max < old_max || new_max > big_max )
         new_max = big_max;
 
-      if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
-        goto Exit;
+      if ( axis->edges == axis->embedded.edges )
+      {
+        if ( FT_NEW_ARRAY( axis->edges, new_max ) )
+          goto Exit;
+        ft_memcpy( axis->edges, axis->embedded.edges,
+                   sizeof ( axis->embedded.edges ) );
+      }
+      else
+      {
+        if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
+          goto Exit;
+      }
 
       axis->max_edges = new_max;
     }
@@ -116,7 +154,8 @@
 
     while ( edge > edges )
     {
-      if ( edge[-1].fpos < fpos )
+      if ( top_to_bottom_hinting ? ( edge[-1].fpos > fpos )
+                                 : ( edge[-1].fpos < fpos ) )
         break;
 
       /* we want the edge with same position and minor direction */
@@ -130,10 +169,6 @@
 
     axis->num_edges++;
 
-    FT_ZERO( edge );
-    edge->fpos = (FT_Short)fpos;
-    edge->dir  = (FT_Char)dir;
-
   Exit:
     *anedge = edge;
     return error;
@@ -183,7 +218,83 @@
   }
 
 
-#define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
+#define AF_INDEX_NUM( ptr, base )  (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
+
+
+  static char*
+  af_print_idx( char* p,
+                int   idx )
+  {
+    if ( idx == -1 )
+    {
+      p[0] = '-';
+      p[1] = '-';
+      p[2] = '\0';
+    }
+    else
+      ft_sprintf( p, "%d", idx );
+
+    return p;
+  }
+
+
+  static int
+  af_get_segment_index( AF_GlyphHints  hints,
+                        int            point_idx,
+                        int            dimension )
+  {
+    AF_AxisHints  axis     = &hints->axis[dimension];
+    AF_Point      point    = hints->points + point_idx;
+    AF_Segment    segments = axis->segments;
+    AF_Segment    limit    = segments + axis->num_segments;
+    AF_Segment    segment;
+
+
+    for ( segment = segments; segment < limit; segment++ )
+    {
+      if ( segment->first <= segment->last )
+      {
+        if ( point >= segment->first && point <= segment->last )
+          break;
+      }
+      else
+      {
+        AF_Point  p = segment->first;
+
+
+        for (;;)
+        {
+          if ( point == p )
+            goto Exit;
+
+          if ( p == segment->last )
+            break;
+
+          p = p->next;
+        }
+      }
+    }
+
+  Exit:
+    if ( segment == limit )
+      return -1;
+
+    return (int)( segment - segments );
+  }
+
+
+  static int
+  af_get_edge_index( AF_GlyphHints  hints,
+                     int            segment_idx,
+                     int            dimension )
+  {
+    AF_AxisHints  axis    = &hints->axis[dimension];
+    AF_Edge       edges   = axis->edges;
+    AF_Segment    segment = axis->segments + segment_idx;
+
+
+    return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
+  }
 
 
 #ifdef __cplusplus
@@ -193,31 +304,59 @@
   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;
+    AF_Point   points  = hints->points;
+    AF_Point   limit   = points + hints->num_points;
+    AF_Point*  contour = hints->contours;
+    AF_Point*  climit  = contour + hints->num_contours;
+    AF_Point   point;
 
 
-    AF_DUMP(( "Table of points:\n"
-              "  [ index |  xorg |  yorg | xscale | yscale"
-              " |  xfit |  yfit |  flags ]\n" ));
+    AF_DUMP(( "Table of points:\n" ));
+
+    if ( hints->num_points )
+      AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags "
+                "  xorg  yorg  xscale  yscale   xfit    yfit" ));
+    else
+      AF_DUMP(( "  (none)\n" ));
 
     for ( point = points; point < limit; point++ )
-      AF_DUMP(( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
-                " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
-                point - points,
+    {
+      int  point_idx     = AF_INDEX_NUM( point, points );
+      int  segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
+      int  segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
+
+      char  buf1[16], buf2[16], buf3[16], buf4[16];
+
+
+      /* insert extra newline at the beginning of a contour */
+      if ( contour < climit && *contour == point )
+      {
+        AF_DUMP(( "\n" ));
+        contour++;
+      }
+
+      AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s"
+                " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
+                point_idx,
+                af_print_idx( buf1,
+                              af_get_edge_index( hints, segment_idx_1, 1 ) ),
+                af_print_idx( buf2, segment_idx_1 ),
+                af_print_idx( buf3,
+                              af_get_edge_index( hints, segment_idx_0, 0 ) ),
+                af_print_idx( buf4, segment_idx_0 ),
+                ( point->flags & AF_FLAG_NEAR )
+                  ? " near "
+                  : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
+                    ? " weak "
+                    : "strong",
+
                 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' : ' '));
+                point->y / 64.0 ));
+    }
     AF_DUMP(( "\n" ));
   }
 #ifdef __cplusplus
@@ -226,7 +365,7 @@
 
 
   static const char*
-  af_edge_flags_to_string( AF_Edge_Flags  flags )
+  af_edge_flags_to_string( FT_UInt  flags )
   {
     static char  temp[32];
     int          pos = 0;
@@ -274,34 +413,37 @@
       AF_Segment    limit    = segments + axis->num_segments;
       AF_Segment    seg;
 
+      char  buf1[16], buf2[16], buf3[16];
+
 
       AF_DUMP(( "Table of %s segments:\n",
                 dimension == AF_DIMENSION_HORZ ? "vertical"
                                                : "horizontal" ));
       if ( axis->num_segments )
-        AF_DUMP(( "  [ index |  pos  |  dir  | from"
-                  " |  to  | link | serif | edge"
-                  " | height | extra |    flags    ]\n" ));
+        AF_DUMP(( "  index   pos   delta   dir   from   to "
+                  "  link  serif  edge"
+                  "  height  extra     flags\n" ));
       else
         AF_DUMP(( "  (none)\n" ));
 
       for ( seg = segments; seg < limit; seg++ )
-        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_DUMP(( "  %5d  %5d  %5d  %5s  %4d  %4d"
+                  "  %4s  %5s  %4s"
+                  "  %6d  %5d  %11s\n",
+                  AF_INDEX_NUM( seg, segments ),
+                  seg->pos,
+                  seg->delta,
                   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 ),
+
+                  af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ),
+                  af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ),
+                  af_print_idx( buf3, 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_edge_flags_to_string( seg->flags ) ));
       AF_DUMP(( "\n" ));
     }
   }
@@ -403,32 +545,43 @@
       AF_Edge       limit = edges + axis->num_edges;
       AF_Edge       edge;
 
+      char  buf1[16], buf2[16];
+
 
       /*
        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
        *        since they have a constant X coordinate.
        */
-      AF_DUMP(( "Table of %s edges:\n",
-                dimension == AF_DIMENSION_HORZ ? "vertical"
-                                               : "horizontal" ));
+      if ( dimension == AF_DIMENSION_HORZ )
+        AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
+                  "vertical",
+                  65536.0 * 64.0 / hints->x_scale,
+                  10.0 * hints->x_scale / 65536.0 / 64.0 ));
+      else
+        AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
+                  "horizontal",
+                  65536.0 * 64.0 / hints->y_scale,
+                  10.0 * hints->y_scale / 65536.0 / 64.0 ));
+
       if ( axis->num_edges )
-        AF_DUMP(( "  [ index |  pos  |  dir  | link"
-                  " | serif | blue | opos  |  pos  |    flags    ]\n" ));
+        AF_DUMP(( "  index    pos     dir   link  serif"
+                  "  blue    opos     pos       flags\n" ));
       else
         AF_DUMP(( "  (none)\n" ));
 
       for ( edge = edges; edge < limit; edge++ )
-        AF_DUMP(( "  [ %5d | %5.2g | %5s | %4d"
-                  " | %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
-                  edge - edges,
+        AF_DUMP(( "  %5d  %7.2f  %5s  %4s  %5s"
+                  "    %c   %7.2f  %7.2f  %11s\n",
+                  AF_INDEX_NUM( 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 ),
+                  af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
+                  af_print_idx( buf2, 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_edge_flags_to_string( edge->flags ) ));
       AF_DUMP(( "\n" ));
     }
   }
@@ -477,15 +630,15 @@
       else
       {
         dir = AF_DIR_DOWN;
-        ll  = dy;
+        ll  = -dy;
         ss  = dx;
       }
     }
 
-    /* return no direction if arm lengths differ too much            */
+    /* return no direction if arm lengths do not differ enough       */
     /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
-    ss *= 14;
-    if ( FT_ABS( ll ) <= FT_ABS( ss ) )
+    /* the long arm is never negative                                */
+    if ( ll <= 14 * FT_ABS( ss ) )
       dir = AF_DIR_NONE;
 
     return dir;
@@ -496,7 +649,8 @@
   af_glyph_hints_init( AF_GlyphHints  hints,
                        FT_Memory      memory )
   {
-    FT_ZERO( hints );
+    /* no need to initialize the embedded items */
+    FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) );
     hints->memory = memory;
   }
 
@@ -504,13 +658,15 @@
   FT_LOCAL_DEF( void )
   af_glyph_hints_done( AF_GlyphHints  hints )
   {
-    FT_Memory  memory = hints->memory;
+    FT_Memory  memory;
     int        dim;
 
 
     if ( !( hints && hints->memory ) )
       return;
 
+    memory = hints->memory;
+
     /*
      *  note that we don't need to free the segment and edge
      *  buffers since they are really within the hints->points array
@@ -522,20 +678,24 @@
 
       axis->num_segments = 0;
       axis->max_segments = 0;
-      FT_FREE( axis->segments );
+      if ( axis->segments != axis->embedded.segments )
+        FT_FREE( axis->segments );
 
       axis->num_edges = 0;
       axis->max_edges = 0;
-      FT_FREE( axis->edges );
+      if ( axis->edges != axis->embedded.edges )
+        FT_FREE( axis->edges );
     }
 
-    FT_FREE( hints->contours );
+    if ( hints->contours != hints->embedded.contours )
+      FT_FREE( hints->contours );
     hints->max_contours = 0;
     hints->num_contours = 0;
 
-    FT_FREE( hints->points );
-    hints->num_points = 0;
+    if ( hints->points != hints->embedded.points )
+      FT_FREE( hints->points );
     hints->max_points = 0;
+    hints->num_points = 0;
 
     hints->memory = NULL;
   }
@@ -579,15 +739,27 @@
 
     /* first of all, reallocate the contours array if necessary */
     new_max = (FT_UInt)outline->n_contours;
-    old_max = hints->max_contours;
-    if ( new_max > old_max )
+    old_max = (FT_UInt)hints->max_contours;
+
+    if ( new_max <= AF_CONTOURS_EMBEDDED )
     {
-      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
+      if ( hints->contours == NULL )
+      {
+        hints->contours     = hints->embedded.contours;
+        hints->max_contours = AF_CONTOURS_EMBEDDED;
+      }
+    }
+    else if ( new_max > old_max )
+    {
+      if ( hints->contours == hints->embedded.contours )
+        hints->contours = NULL;
+
+      new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */
 
       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
         goto Exit;
 
-      hints->max_contours = new_max;
+      hints->max_contours = (FT_Int)new_max;
     }
 
     /*
@@ -596,15 +768,27 @@
      *  hint metrics appropriately
      */
     new_max = (FT_UInt)( outline->n_points + 2 );
-    old_max = hints->max_points;
-    if ( new_max > old_max )
+    old_max = (FT_UInt)hints->max_points;
+
+    if ( new_max <= AF_POINTS_EMBEDDED )
     {
-      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
+      if ( hints->points == NULL )
+      {
+        hints->points     = hints->embedded.points;
+        hints->max_points = AF_POINTS_EMBEDDED;
+      }
+    }
+    else if ( new_max > old_max )
+    {
+      if ( hints->points == hints->embedded.points )
+        hints->points = NULL;
+
+      new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */
 
       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
         goto Exit;
 
-      hints->max_points = new_max;
+      hints->max_points = (FT_Int)new_max;
     }
 
     hints->num_points   = outline->n_points;
@@ -639,18 +823,26 @@
       AF_Point  point;
       AF_Point  point_limit = points + hints->num_points;
 
+      /* value 20 in `near_limit' is heuristic */
+      FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
+      FT_Int   near_limit   = 20 * units_per_em / 2048;
+
 
       /* compute coordinates & Bezier flags, next and prev */
       {
         FT_Vector*  vec           = outline->points;
         char*       tag           = outline->tags;
-        AF_Point    end           = points + outline->contours[0];
+        FT_Short    endpoint      = outline->contours[0];
+        AF_Point    end           = points + endpoint;
         AF_Point    prev          = end;
         FT_Int      contour_index = 0;
 
 
         for ( point = points; point < point_limit; point++, vec++, tag++ )
         {
+          FT_Pos  out_x, out_y;
+
+
           point->in_dir  = (FT_Char)AF_DIR_NONE;
           point->out_dir = (FT_Char)AF_DIR_NONE;
 
@@ -659,6 +851,9 @@
           point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
           point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
 
+          end->fx = (FT_Short)outline->points[endpoint].x;
+          end->fy = (FT_Short)outline->points[endpoint].y;
+
           switch ( FT_CURVE_TAG( *tag ) )
           {
           case FT_CURVE_TAG_CONIC:
@@ -671,6 +866,12 @@
             point->flags = AF_FLAG_NONE;
           }
 
+          out_x = point->fx - prev->fx;
+          out_y = point->fy - prev->fy;
+
+          if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
+            prev->flags |= AF_FLAG_NEAR;
+
           point->prev = prev;
           prev->next  = point;
           prev        = point;
@@ -679,8 +880,9 @@
           {
             if ( ++contour_index < outline->n_contours )
             {
-              end  = points + outline->contours[contour_index];
-              prev = end;
+              endpoint = outline->contours[contour_index];
+              end      = points + endpoint;
+              prev     = end;
             }
           }
         }
@@ -706,17 +908,15 @@
          *  Compute directions of `in' and `out' vectors.
          *
          *  Note that distances between points that are very near to each
-         *  other are accumulated.  In other words, the auto-hinter
+         *  other are accumulated.  In other words, the auto-hinter either
          *  prepends the small vectors between near points to the first
-         *  non-near vector.  All intermediate points are tagged as
-         *  weak; the directions are adjusted also to be equal to the
-         *  accumulated one.
+         *  non-near vector, or the sum of small vector lengths exceeds a
+         *  threshold, thus `grouping' the small vectors.  All intermediate
+         *  points are tagged as weak; the directions are adjusted also to
+         *  be equal to the accumulated one.
          */
 
-        /* value 20 in `near_limit' is heuristic */
-        FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
-        FT_Int   near_limit   = 20 * units_per_em / 2048;
-        FT_Int   near_limit2  = 2 * near_limit - 1;
+        FT_Int  near_limit2 = 2 * near_limit - 1;
 
         AF_Point*  contour;
         AF_Point*  contour_limit = hints->contours + hints->num_contours;
@@ -729,8 +929,6 @@
 
           FT_Pos  out_x, out_y;
 
-          FT_Bool  is_first;
-
 
           /* since the first point of a contour could be part of a */
           /* series of near points, go backwards to find the first */
@@ -765,7 +963,7 @@
           /* now loop over all points of the contour to get */
           /* `in' and `out' vector directions               */
 
-          curr  = first;
+          curr = first;
 
           /*
            *  We abuse the `u' and `v' fields to store index deltas to the
@@ -781,18 +979,14 @@
           out_x = 0;
           out_y = 0;
 
-          is_first = 1;
-
-          for ( point = first;
-                point != first || is_first;
-                point = point->next )
+          next = first;
+          do
           {
             AF_Direction  out_dir;
 
 
-            is_first = 0;
-
-            next = point->next;
+            point = next;
+            next  = point->next;
 
             out_x += next->fx - point->fx;
             out_y += next->fy - point->fy;
@@ -823,7 +1017,8 @@
 
             out_x = 0;
             out_y = 0;
-          }
+
+          } while ( next != first );
         }
 
         /*
@@ -1053,7 +1248,7 @@
     AF_AxisHints  axis        = &hints->axis[dim];
     AF_Edge       edges       = axis->edges;
     AF_Edge       edge_limit  = edges + axis->num_edges;
-    AF_Flags      touch_flag;
+    FT_UInt       touch_flag;
 
 
     if ( dim == AF_DIMENSION_HORZ )
@@ -1079,8 +1274,7 @@
         /* if this point is candidate to weak interpolation, we       */
         /* interpolate it after all strong points have been processed */
 
-        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
-             !( point->flags & AF_FLAG_INFLECTION )         )
+        if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) )
           continue;
 
         if ( dim == AF_DIMENSION_VERT )
@@ -1235,33 +1429,27 @@
                  AF_Point  ref2 )
   {
     AF_Point  p;
-    FT_Pos    u;
-    FT_Pos    v1 = ref1->v;
-    FT_Pos    v2 = ref2->v;
-    FT_Pos    d1 = ref1->u - v1;
-    FT_Pos    d2 = ref2->u - v2;
+    FT_Pos    u, v1, v2, u1, u2, d1, d2;
 
 
     if ( p1 > p2 )
       return;
 
-    if ( v1 == v2 )
+    if ( ref1->v > ref2->v )
     {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v1 )
-          u += d1;
-        else
-          u += d2;
-
-        p->u = u;
-      }
-      return;
+      p    = ref1;
+      ref1 = ref2;
+      ref2 = p;
     }
 
-    if ( v1 < v2 )
+    v1 = ref1->v;
+    v2 = ref2->v;
+    u1 = ref1->u;
+    u2 = ref2->u;
+    d1 = u1 - v1;
+    d2 = u2 - v2;
+
+    if ( u1 == u2 || v1 == v2 )
     {
       for ( p = p1; p <= p2; p++ )
       {
@@ -1272,23 +1460,26 @@
         else if ( u >= v2 )
           u += d2;
         else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+          u = u1;
 
         p->u = u;
       }
     }
     else
     {
+      FT_Fixed  scale = FT_DivFix( u2 - u1, v2 - v1 );
+
+
       for ( p = p1; p <= p2; p++ )
       {
         u = p->v;
 
-        if ( u <= v2 )
-          u += d2;
-        else if ( u >= v1 )
+        if ( u <= v1 )
           u += d1;
+        else if ( u >= v2 )
+          u += d2;
         else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+          u = u1 + FT_MulFix( u - v1, scale );
 
         p->u = u;
       }
@@ -1307,7 +1498,7 @@
     AF_Point   point_limit   = points + hints->num_points;
     AF_Point*  contour       = hints->contours;
     AF_Point*  contour_limit = contour + hints->num_contours;
-    AF_Flags   touch_flag;
+    FT_UInt    touch_flag;
     AF_Point   point;
     AF_Point   end_point;
     AF_Point   first_point;
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index c0ebd0d..4fdf732 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (specification).                        */
 /*                                                                         */
-/*  Copyright 2003-2008, 2010-2012, 2014 by                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFHINTS_H__
-#define __AFHINTS_H__
+#ifndef AFHINTS_H_
+#define AFHINTS_H_
 
 #include "aftypes.h"
 
@@ -72,13 +72,9 @@
    *    `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 writing system.
-   *
-   *    A segment must have at least two points, except in the case of
-   *    `fake' segments that are generated to hint metrics appropriately,
-   *    and which consist of a single point.
+   *    A segment is a series of at least two consecutive points that are
+   *    approximately aligned along a coordinate axis.  The analysis to do
+   *    so is specific to a writing system.
    *
    *
    *  Edges
@@ -148,7 +144,7 @@
    *    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
+   *    module that takes care of the `latin' writing system) has
    *
    *      best segment_1 = segment_2 && best segment_2 != segment_1
    *
@@ -178,19 +174,19 @@
    *
    *  Strong Points
    *
-   *    Experience has shown that points which are not part of an edge need
-   *    to be interpolated linearly between their two closest edges, even if
-   *    these are not part of the contour of those particular points.
-   *    Typical candidates for this are
+   *    Experience has shown that points not part of an edge need to be
+   *    interpolated linearly between their two closest edges, even if these
+   *    are not part of the contour of those particular points.  Typical
+   *    candidates for this are
    *
    *    - angle points (i.e., points where the `in' and `out' direction
    *      differ greatly)
    *
    *    - inflection points (i.e., where the `in' and `out' angles are the
    *      same, but the curvature changes sign) [currently, such points
-   *      aren't handled in the auto-hinter]
+   *      aren't handled specially in the auto-hinter]
    *
-   *    `af_glyph_hints_align_strong_points' is the function which takes
+   *    `af_glyph_hints_align_strong_points' is the function that takes
    *    care of such situations; it is equivalent to the TrueType `IP'
    *    hinting instruction.
    *
@@ -211,46 +207,30 @@
 
 
   /* point hint flags */
-  typedef enum  AF_Flags_
-  {
-    AF_FLAG_NONE = 0,
+#define AF_FLAG_NONE  0
 
-    /* point type flags */
-    AF_FLAG_CONIC   = 1 << 0,
-    AF_FLAG_CUBIC   = 1 << 1,
-    AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
+  /* point type flags */
+#define AF_FLAG_CONIC    ( 1U << 0 )
+#define AF_FLAG_CUBIC    ( 1U << 1 )
+#define AF_FLAG_CONTROL  ( AF_FLAG_CONIC | AF_FLAG_CUBIC )
 
-    /* point extremum flags */
-    AF_FLAG_EXTREMA_X = 1 << 2,
-    AF_FLAG_EXTREMA_Y = 1 << 3,
+  /* point touch flags */
+#define AF_FLAG_TOUCH_X  ( 1U << 2 )
+#define AF_FLAG_TOUCH_Y  ( 1U << 3 )
 
-    /* point roundness flags */
-    AF_FLAG_ROUND_X = 1 << 4,
-    AF_FLAG_ROUND_Y = 1 << 5,
+  /* candidates for weak interpolation have this flag set */
+#define AF_FLAG_WEAK_INTERPOLATION  ( 1U << 4 )
 
-    /* point touch flags */
-    AF_FLAG_TOUCH_X = 1 << 6,
-    AF_FLAG_TOUCH_Y = 1 << 7,
-
-    /* candidates for weak interpolation have this flag set */
-    AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
-
-    /* all inflection points in the outline have this flag set */
-    AF_FLAG_INFLECTION = 1 << 9
-
-  } AF_Flags;
+  /* the distance to the next point is very small */
+#define AF_FLAG_NEAR  ( 1U << 5 )
 
 
   /* edge hint flags */
-  typedef enum  AF_Edge_Flags_
-  {
-    AF_EDGE_NORMAL  = 0,
-    AF_EDGE_ROUND   = 1 << 0,
-    AF_EDGE_SERIF   = 1 << 1,
-    AF_EDGE_DONE    = 1 << 2,
-    AF_EDGE_NEUTRAL = 1 << 3  /* set if edge aligns to a neutral blue zone */
-
-  } AF_Edge_Flags;
+#define AF_EDGE_NORMAL  0
+#define AF_EDGE_ROUND    ( 1U << 0 )
+#define AF_EDGE_SERIF    ( 1U << 1 )
+#define AF_EDGE_DONE     ( 1U << 2 )
+#define AF_EDGE_NEUTRAL  ( 1U << 3 ) /* edge aligns to a neutral blue zone */
 
 
   typedef struct AF_PointRec_*    AF_Point;
@@ -280,6 +260,7 @@
     FT_Byte     flags;       /* edge/segment flags for this segment */
     FT_Char     dir;         /* segment direction                   */
     FT_Short    pos;         /* position of segment                 */
+    FT_Short    delta;       /* deviation from segment position     */
     FT_Short    min_coord;   /* minimum coordinate of segment       */
     FT_Short    max_coord;   /* maximum coordinate of segment       */
     FT_Short    height;      /* the hinted segment height           */
@@ -289,7 +270,6 @@
 
     AF_Segment  link;        /* (stem) link segment        */
     AF_Segment  serif;       /* primary segment for serifs */
-    FT_Pos      num_linked;  /* number of linked segments  */
     FT_Pos      score;       /* used during stem matching  */
     FT_Pos      len;         /* used during stem matching  */
 
@@ -312,7 +292,6 @@
     AF_Width    blue_edge;  /* non-NULL if this is a blue edge */
     AF_Edge     link;       /* link edge                       */
     AF_Edge     serif;      /* primary edge for serifs         */
-    FT_Short    num_linked; /* number of linked edges          */
     FT_Int      score;      /* used during stem matching       */
 
     AF_Segment  first;      /* first segment in edge */
@@ -320,6 +299,8 @@
 
   } AF_EdgeRec;
 
+#define AF_SEGMENTS_EMBEDDED  18   /* number of embedded segments   */
+#define AF_EDGES_EMBEDDED     12   /* number of embedded edges      */
 
   typedef struct  AF_AxisHintsRec_
   {
@@ -336,9 +317,20 @@
 
     AF_Direction  major_dir;    /* either vertical or horizontal */
 
+    /* two arrays to avoid allocation penalty */
+    struct
+    {
+      AF_SegmentRec  segments[AF_SEGMENTS_EMBEDDED];
+      AF_EdgeRec     edges[AF_EDGES_EMBEDDED];
+    } embedded;
+
+
   } AF_AxisHintsRec, *AF_AxisHints;
 
 
+#define AF_POINTS_EMBEDDED     96   /* number of embedded points   */
+#define AF_CONTOURS_EMBEDDED    8   /* number of embedded contours */
+
   typedef struct  AF_GlyphHintsRec_
   {
     FT_Memory        memory;
@@ -367,6 +359,14 @@
     FT_Pos           xmin_delta;    /* used for warping */
     FT_Pos           xmax_delta;
 
+    /* Two arrays to avoid allocation penalty.            */
+    /* The `embedded' structure must be the last element! */
+    struct
+    {
+      AF_Point       contours[AF_CONTOURS_EMBEDDED];
+      AF_PointRec    points[AF_POINTS_EMBEDDED];
+    } embedded;
+
   } AF_GlyphHintsRec;
 
 
@@ -384,9 +384,6 @@
           ( !_af_debug_disable_vert_hints                          && \
             !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
 
-#define AF_HINTS_DO_ADVANCE( h )                                \
-          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
-
 #define AF_HINTS_DO_BLUES( h )  ( !_af_debug_disable_blue_hints )
 
 #else /* !FT_DEBUG_AUTOFIT */
@@ -397,14 +394,19 @@
 #define AF_HINTS_DO_VERTICAL( h )                                \
           !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
 
-#define AF_HINTS_DO_ADVANCE( h )                                \
-          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
-
 #define AF_HINTS_DO_BLUES( h )  1
 
 #endif /* !FT_DEBUG_AUTOFIT */
 
 
+#define AF_HINTS_DO_ADVANCE( h )                                \
+          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
+
+#define AF_HINTS_DO_WARP( h )                                  \
+          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
+
+
+
   FT_LOCAL( AF_Direction )
   af_direction_compute( FT_Pos  dx,
                         FT_Pos  dy );
@@ -419,6 +421,7 @@
   af_axis_hints_new_edge( AF_AxisHints  axis,
                           FT_Int        fpos,
                           AF_Direction  dir,
+                          FT_Bool       top_to_bottom_hinting,
                           FT_Memory     memory,
                           AF_Edge      *edge );
 
@@ -472,7 +475,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFHINTS_H__ */
+#endif /* AFHINTS_H_ */
 
 
 /* END */
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 197881b..097a2b2 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for Indic writing system (body).        */
 /*                                                                         */
-/*  Copyright 2007, 2011-2013 by                                           */
+/*  Copyright 2007-2016 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,       */
@@ -79,12 +79,29 @@
 
 
   static FT_Error
-  af_indic_hints_apply( AF_GlyphHints  hints,
+  af_indic_hints_apply( FT_UInt        glyph_index,
+                        AF_GlyphHints  hints,
                         FT_Outline*    outline,
                         AF_CJKMetrics  metrics )
   {
     /* use CJK routines */
-    return af_cjk_hints_apply( hints, outline, metrics );
+    return af_cjk_hints_apply( glyph_index, hints, outline, metrics );
+  }
+
+
+  /* Extract standard_width from writing system/script specific */
+  /* metrics class.                                             */
+
+  static void
+  af_indic_get_standard_widths( AF_CJKMetrics  metrics,
+                                FT_Pos*        stdHW,
+                                FT_Pos*        stdVW )
+  {
+    if ( stdHW )
+      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+    if ( stdVW )
+      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
   }
 
 
@@ -107,6 +124,7 @@
     (AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init,
     (AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths,
 
     (AF_WritingSystem_InitHintsFunc)   af_indic_hints_init,
     (AF_WritingSystem_ApplyHintsFunc)  af_indic_hints_apply
@@ -126,6 +144,7 @@
     (AF_WritingSystem_InitMetricsFunc) NULL,
     (AF_WritingSystem_ScaleMetricsFunc)NULL,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)NULL,
 
     (AF_WritingSystem_InitHintsFunc)   NULL,
     (AF_WritingSystem_ApplyHintsFunc)  NULL
diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h
index 9e13cf7..0772e07 100644
--- a/src/autofit/afindic.h
+++ b/src/autofit/afindic.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter hinting routines for Indic writing system                */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2007, 2012, 2013 by                                          */
+/*  Copyright 2007-2016 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,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFINDIC_H__
-#define __AFINDIC_H__
+#ifndef AFINDIC_H_
+#define AFINDIC_H_
 
 #include "afhints.h"
 
@@ -35,7 +35,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFINDIC_H__ */
+#endif /* AFINDIC_H_ */
 
 
 /* END */
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index a1f2b33..db7aaff 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin writing system (body).        */
 /*                                                                         */
-/*  Copyright 2003-2014 by                                                 */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -41,6 +41,10 @@
 #define FT_COMPONENT  trace_aflatin
 
 
+  /* needed for computation of round vs. flat segments */
+#define FLAT_THRESHOLD( x )  ( x / 14 )
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -75,7 +79,6 @@
     {
       FT_Error            error;
       FT_ULong            glyph_index;
-      FT_Long             y_offset;
       int                 dim;
       AF_LatinMetricsRec  dummy[1];
       AF_Scaler           scaler = &dummy->root.scaler;
@@ -88,52 +91,63 @@
       AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
                                        [style_class->script];
 
-      FT_UInt32  standard_char;
+      void*        shaper_buf;
+      const char*  p;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+      FT_ULong  ch = 0;
+#endif
+
+      p          = script_class->standard_charstring;
+      shaper_buf = af_shaper_buf_create( face );
 
       /*
-       * We check more than a single standard character to catch features
-       * like `c2sc' (small caps from caps) that don't contain lowercase
-       * letters by definition, or other features that mainly operate on
-       * numerals.
+       * We check a list of standard characters to catch features like
+       * `c2sc' (small caps from caps) that don't contain lowercase letters
+       * by definition, or other features that mainly operate on numerals.
+       * The first match wins.
        */
 
-      standard_char = script_class->standard_char1;
-      af_get_char_index( &metrics->root,
-                         standard_char,
-                         &glyph_index,
-                         &y_offset );
-      if ( !glyph_index )
+      glyph_index = 0;
+      while ( *p )
       {
-        if ( script_class->standard_char2 )
-        {
-          standard_char = script_class->standard_char2;
-          af_get_char_index( &metrics->root,
-                             standard_char,
-                             &glyph_index,
-                             &y_offset );
-          if ( !glyph_index )
-          {
-            if ( script_class->standard_char3 )
-            {
-              standard_char = script_class->standard_char3;
-              af_get_char_index( &metrics->root,
-                                 standard_char,
-                                 &glyph_index,
-                                 &y_offset );
-              if ( !glyph_index )
-                goto Exit;
-            }
-            else
-              goto Exit;
-          }
-        }
-        else
-          goto Exit;
+        unsigned int  num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+#endif
+
+
+        while ( *p == ' ' )
+          p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
+
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
+
+        /* otherwise exit loop if we have a result */
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
+        if ( glyph_index )
+          break;
       }
 
+      af_shaper_buf_destroy( face, shaper_buf );
+
+      if ( !glyph_index )
+        goto Exit;
+
       FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
-                  standard_char, glyph_index ));
+                  ch, glyph_index ));
 
       error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
       if ( error || face->glyph->outline.n_points <= 0 )
@@ -261,8 +275,8 @@
     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_UInt       num_flats;
+    FT_UInt       num_rounds;
 
     AF_LatinBlue  blue;
     FT_Error      error;
@@ -274,6 +288,10 @@
     AF_Blue_Stringset         bss = sc->blue_stringset;
     const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
 
+    FT_Pos  flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
+
+    void*  shaper_buf;
+
 
     /* we walk over the blue character strings as specified in the */
     /* style's entry in the `af_blue_stringset' array              */
@@ -282,11 +300,15 @@
                 "============================\n"
                 "\n" ));
 
+    shaper_buf = af_shaper_buf_create( face );
+
     for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
       const char*  p = &af_blue_strings[bs->string];
       FT_Pos*      blue_ref;
       FT_Pos*      blue_shoot;
+      FT_Pos       ascender;
+      FT_Pos       descender;
 
 
 #ifdef FT_DEBUG_LEVEL_TRACE
@@ -305,6 +327,11 @@
             FT_TRACE5(( "top" ));
             have_flag = 1;
           }
+          else if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+          {
+            FT_TRACE5(( "sub top" ));
+            have_flag = 1;
+          }
 
           if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
           {
@@ -338,393 +365,482 @@
 
       num_flats  = 0;
       num_rounds = 0;
+      ascender   = 0;
+      descender  = 0;
 
       while ( *p )
       {
-        FT_ULong    ch;
         FT_ULong    glyph_index;
         FT_Long     y_offset;
-        FT_Pos      best_y;                            /* same as points.y */
         FT_Int      best_point, best_contour_first, best_contour_last;
         FT_Vector*  points;
-        FT_Bool     round = 0;
+
+        FT_Pos   best_y_extremum;                      /* same as points.y */
+        FT_Bool  best_round = 0;
+
+        unsigned int  i, num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+        FT_ULong     ch;
+#endif
 
 
-        GET_UTF8_CHAR( ch, p );
+        while ( *p == ' ' )
+          p++;
 
-        /* load the character in the face -- skip unknown or empty ones */
-        af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
-        if ( glyph_index == 0 )
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
+
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+
+        if ( !num_idx )
         {
           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 )
+        if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+          best_y_extremum = FT_INT_MIN;
+        else
+          best_y_extremum = FT_INT_MAX;
+
+        /* iterate over all glyph elements of the character cluster */
+        /* and get the data of the `biggest' one                    */
+        for ( i = 0; i < num_idx; i++ )
         {
-          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_y             = 0;  /* make compiler happy */
-        best_contour_first = 0;  /* ditto */
-        best_contour_last  = 0;  /* ditto */
-
-        {
-          FT_Int  nn;
-          FT_Int  first = 0;
-          FT_Int  last  = -1;
+          FT_Pos   best_y;
+          FT_Bool  round = 0;
 
 
-          for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
+          /* load the character in the face -- skip unknown or empty ones */
+          glyph_index = af_shaper_get_elem( &metrics->root,
+                                            shaper_buf,
+                                            i,
+                                            NULL,
+                                            &y_offset );
+          if ( glyph_index == 0 )
           {
-            FT_Int  old_best_point = best_point;
-            FT_Int  pp;
-
-
-            last = outline.contours[nn];
-
-            /* Avoid single-point contours since they are never rasterized. */
-            /* In some fonts, they correspond to mark attachment points     */
-            /* that are way outside of the glyph's real outline.            */
-            if ( last <= first )
-              continue;
-
-            if ( AF_LATIN_IS_TOP_BLUE( bs ) )
-            {
-              for ( pp = first; pp <= last; pp++ )
-                if ( best_point < 0 || points[pp].y > best_y )
-                {
-                  best_point = pp;
-                  best_y     = points[pp].y;
-                }
-            }
-            else
-            {
-              for ( pp = first; pp <= last; pp++ )
-                if ( best_point < 0 || points[pp].y < best_y )
-                {
-                  best_point = pp;
-                  best_y     = points[pp].y;
-                }
-            }
-
-            if ( best_point != old_best_point )
-            {
-              best_contour_first = first;
-              best_contour_last  = last;
-            }
-          }
-        }
-
-        /* now check whether the point belongs to a straight or round   */
-        /* segment; we first need to find in which contour the extremum */
-        /* lies, then inspect its previous and next points              */
-        if ( best_point >= 0 )
-        {
-          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;
-            best_on_point_last  = best_point;
-          }
-          else
-          {
-            best_on_point_first = -1;
-            best_on_point_last  = -1;
+            FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
+            continue;
           }
 
-          /* 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;
-
-          do
+          error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+          outline = face->glyph->outline;
+          /* reject glyphs that don't produce any rendering */
+          if ( error || outline.n_points <= 2 )
           {
-            if ( prev > best_contour_first )
-              prev--;
+#ifdef FT_DEBUG_LEVEL_TRACE
+            if ( num_idx == 1 )
+              FT_TRACE5(( "  U+%04lX contains no (usable) outlines\n", ch ));
             else
-              prev = best_contour_last;
+              FT_TRACE5(( "  component %d of cluster starting with U+%04lX"
+                          " contains no (usable) outlines\n", i, ch ));
+#endif
+            continue;
+          }
 
-            dist = FT_ABS( points[prev].y - best_y );
-            /* accept a small distance or a small angle (both values are */
-            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
-            if ( dist > 5 )
-              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
-                break;
+          /* now compute min or max point indices and coordinates */
+          points             = outline.points;
+          best_point         = -1;
+          best_y             = 0;  /* make compiler happy */
+          best_contour_first = 0;  /* ditto */
+          best_contour_last  = 0;  /* ditto */
 
-            best_segment_first = prev;
-
-            if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
-            {
-              best_on_point_first = prev;
-              if ( best_on_point_last < 0 )
-                best_on_point_last = prev;
-            }
-
-          } while ( prev != best_point );
-
-          do
           {
-            if ( next < best_contour_last )
-              next++;
-            else
-              next = best_contour_first;
+            FT_Int  nn;
+            FT_Int  first = 0;
+            FT_Int  last  = -1;
 
-            dist = FT_ABS( points[next].y - best_y );
-            if ( dist > 5 )
-              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 )
+            for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
             {
-              best_on_point_last = next;
-              if ( best_on_point_first < 0 )
-                best_on_point_first = next;
-            }
-
-          } while ( next != best_point );
-
-          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;
+              FT_Int  old_best_point = best_point;
+              FT_Int  pp;
 
 
-            dist = FT_ABS( points[best_segment_last].x -
-                             points[best_segment_first].x );
+              last = outline.contours[nn];
 
-            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;
-
-              /* we intentionally declare these two variables        */
-              /* outside of the loop since various compilers emit    */
-              /* incorrect warning messages otherwise, talking about */
-              /* `possibly uninitialized variables'                  */
-              FT_Int  p_first = 0;            /* make compiler happy */
-              FT_Int  p_last  = 0;
-
-              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 )
+              /* Avoid single-point contours since they are never      */
+              /* rasterized.  In some fonts, they correspond to mark   */
+              /* attachment points that are way outside of the glyph's */
+              /* real outline.                                         */
+              if ( last <= first )
                 continue;
 
-              left2right = FT_BOOL( points[prev].x < points[best_point].x );
-
-              first = best_segment_last;
-              last  = first;
-              hit   = 0;
-
-              do
+              if ( AF_LATIN_IS_TOP_BLUE( bs )     ||
+                   AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
               {
-                FT_Bool  l2r;
-                FT_Pos   d;
-
-
-                if ( !hit )
+                for ( pp = first; pp <= last; pp++ )
                 {
-                  /* 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 )
+                  if ( best_point < 0 || points[pp].y > best_y )
                   {
-                    p_first = first;
-                    p_last  = first;
+                    best_point = pp;
+                    best_y     = points[pp].y;
+                    ascender   = FT_MAX( ascender, best_y + y_offset );
                   }
                   else
+                    descender = FT_MIN( descender, points[pp].y + y_offset );
+                }
+              }
+              else
+              {
+                for ( pp = first; pp <= last; pp++ )
+                {
+                  if ( best_point < 0 || points[pp].y < best_y )
                   {
-                    p_first = -1;
-                    p_last  = -1;
+                    best_point = pp;
+                    best_y     = points[pp].y;
+                    descender  = FT_MIN( descender, best_y + y_offset );
+                  }
+                  else
+                    ascender = FT_MAX( ascender, points[pp].y + y_offset );
+                }
+              }
+
+              if ( best_point != old_best_point )
+              {
+                best_contour_first = first;
+                best_contour_last  = last;
+              }
+            }
+          }
+
+          /* now check whether the point belongs to a straight or round   */
+          /* segment; we first need to find in which contour the extremum */
+          /* lies, then inspect its previous and next points              */
+          if ( best_point >= 0 )
+          {
+            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;
+              best_on_point_last  = best_point;
+            }
+            else
+            {
+              best_on_point_first = -1;
+              best_on_point_last  = -1;
+            }
+
+            /* 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;
+
+            do
+            {
+              if ( prev > best_contour_first )
+                prev--;
+              else
+                prev = best_contour_last;
+
+              dist = FT_ABS( points[prev].y - best_y );
+              /* accept a small distance or a small angle (both values are */
+              /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
+              if ( dist > 5 )
+                if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+                  break;
+
+              best_segment_first = prev;
+
+              if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+              {
+                best_on_point_first = prev;
+                if ( best_on_point_last < 0 )
+                  best_on_point_last = prev;
+              }
+
+            } while ( prev != best_point );
+
+            do
+            {
+              if ( next < best_contour_last )
+                next++;
+              else
+                next = best_contour_first;
+
+              dist = FT_ABS( points[next].y - best_y );
+              if ( dist > 5 )
+                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;
+                if ( best_on_point_first < 0 )
+                  best_on_point_first = next;
+              }
+
+            } while ( next != best_point );
+
+            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;
+
+                /* we intentionally declare these two variables        */
+                /* outside of the loop since various compilers emit    */
+                /* incorrect warning messages otherwise, talking about */
+                /* `possibly uninitialized variables'                  */
+                FT_Int  p_first = 0;            /* make compiler happy */
+                FT_Int  p_last  = 0;
+
+                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;
+
+
+                  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;
                   }
 
-                  hit = 1;
-                }
+                  if ( last < best_contour_last )
+                    last++;
+                  else
+                    last = best_contour_first;
 
-                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 )
+                  if ( FT_ABS( best_y - points[first].y ) > height_threshold )
                   {
+                    /* vertical distance too large */
                     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 )
-                      {
-                        if ( last > best_contour_first )
-                          last--;
-                        else
-                          last = best_contour_last;
-                        break;
-                      }
-
-                    p_last = last;
-
-                    if ( FT_CURVE_TAG( outline.tags[last] ) ==
-                           FT_CURVE_TAG_ON )
+                  /* 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 )
                     {
-                      p_last = last;
-                      if ( p_first < 0 )
-                        p_first = last;
+                      hit = 0;
+                      continue;
                     }
 
-                  } while ( last != best_segment_first );
+                  if ( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
+                  {
+                    p_last = last;
+                    if ( p_first < 0 )
+                      p_first = last;
+                  }
 
-                  best_y = points[first].y;
+                  l2r = FT_BOOL( points[first].x < points[last].x );
+                  d   = FT_ABS( points[last].x - points[first].x );
 
-                  best_segment_first = first;
-                  best_segment_last  = last;
+                  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;
 
-                  best_on_point_first = p_first;
-                  best_on_point_last  = p_last;
+                      d = FT_ABS( points[last].y - points[first].y );
+                      if ( d > 5 )
+                        if ( FT_ABS( points[next].x - points[first].x ) <=
+                               20 * dist )
+                        {
+                          if ( last > best_contour_first )
+                            last--;
+                          else
+                            last = best_contour_last;
+                          break;
+                        }
 
-                  break;
-                }
+                      p_last = last;
 
-              } while ( last != best_segment_first );
+                      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 );
+              }
+            }
+
+            /* for computing blue zones, we add the y offset as returned */
+            /* by the currently used OpenType feature -- for example,    */
+            /* superscript glyphs might be identical to subscript glyphs */
+            /* with a vertical shift                                     */
+            best_y += y_offset;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+            if ( num_idx == 1 )
+              FT_TRACE5(( "  U+%04lX: best_y = %5ld", ch, best_y ));
+            else
+              FT_TRACE5(( "  component %d of cluster starting with U+%04lX:"
+                          " best_y = %5ld", i, ch, best_y ));
+#endif
+
+            /* 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 a heuristic threshold         */
+            /*   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_ABS( points[best_on_point_last].x -
+                           points[best_on_point_first].x ) ) >
+                   flat_threshold                                       )
+              round = 0;
+            else
+              round = FT_BOOL(
+                        FT_CURVE_TAG( outline.tags[best_segment_first] ) !=
+                          FT_CURVE_TAG_ON                                   ||
+                        FT_CURVE_TAG( outline.tags[best_segment_last]  ) !=
+                          FT_CURVE_TAG_ON                                   );
+
+            if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
+            {
+              /* only use flat segments for a neutral blue zone */
+              FT_TRACE5(( " (round, skipped)\n" ));
+              continue;
+            }
+
+            FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+          }
+
+          if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+          {
+            if ( best_y > best_y_extremum )
+            {
+              best_y_extremum = best_y;
+              best_round      = round;
+            }
+          }
+          else
+          {
+            if ( best_y < best_y_extremum )
+            {
+              best_y_extremum = best_y;
+              best_round      = round;
             }
           }
 
-          /* for computing blue zones, we add the y offset as returned */
-          /* by the currently used OpenType feature -- for example,    */
-          /* superscript glyphs might be identical to subscript glyphs */
-          /* with a vertical shift                                     */
-          best_y += y_offset;
+        } /* end for loop */
 
-          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 -
-                                  points[best_on_point_first].x ) ) >
-                 metrics->units_per_em / 8                            )
-            round = 0;
+        if ( !( best_y_extremum == FT_INT_MIN ||
+                best_y_extremum == FT_INT_MAX ) )
+        {
+          if ( best_round )
+            rounds[num_rounds++] = best_y_extremum;
           else
-            round = FT_BOOL(
-                      FT_CURVE_TAG( outline.tags[best_segment_first] ) !=
-                        FT_CURVE_TAG_ON                                   ||
-                      FT_CURVE_TAG( outline.tags[best_segment_last]  ) !=
-                        FT_CURVE_TAG_ON                                   );
-
-          if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
-          {
-            /* only use flat segments for a neutral blue zone */
-            FT_TRACE5(( " (round, skipped)\n" ));
-            continue;
-          }
-
-          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+            flats[num_flats++]   = best_y_extremum;
         }
 
-        if ( round )
-          rounds[num_rounds++] = best_y;
-        else
-          flats[num_flats++]   = best_y;
-      }
+      } /* end while loop */
 
       if ( num_flats == 0 && num_rounds == 0 )
       {
@@ -774,7 +890,8 @@
         FT_Bool  over_ref = FT_BOOL( shoot > ref );
 
 
-        if ( AF_LATIN_IS_TOP_BLUE( bs ) ^ over_ref )
+        if ( ( AF_LATIN_IS_TOP_BLUE( bs )    ||
+               AF_LATIN_IS_SUB_TOP_BLUE( bs) ) ^ over_ref )
         {
           *blue_ref   =
           *blue_shoot = ( shoot + ref ) / 2;
@@ -784,9 +901,14 @@
         }
       }
 
+      blue->ascender  = ascender;
+      blue->descender = descender;
+
       blue->flags = 0;
       if ( AF_LATIN_IS_TOP_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_TOP;
+      if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+        blue->flags |= AF_LATIN_BLUE_SUB_TOP;
       if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_NEUTRAL;
 
@@ -801,7 +923,10 @@
       FT_TRACE5(( "    -> reference = %ld\n"
                   "       overshoot = %ld\n",
                   *blue_ref, *blue_shoot ));
-    }
+
+    } /* end for loop */
+
+    af_shaper_buf_destroy( face, shaper_buf );
 
     FT_TRACE5(( "\n" ));
 
@@ -815,27 +940,36 @@
   af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
                                  FT_Face          face )
   {
-    FT_UInt   i;
     FT_Bool   started = 0, same_width = 1;
     FT_Fixed  advance, old_advance = 0;
 
+    void*  shaper_buf;
 
-    /* digit `0' is 0x30 in all supported charmaps */
-    for ( i = 0x30; i <= 0x39; i++ )
+    /* in all supported charmaps, digits have character codes 0x30-0x39 */
+    const char   digits[] = "0 1 2 3 4 5 6 7 8 9";
+    const char*  p;
+
+
+    p          = digits;
+    shaper_buf = af_shaper_buf_create( face );
+
+    while ( *p )
     {
-      FT_ULong  glyph_index;
-      FT_Long   y_offset;
+      FT_ULong      glyph_index;
+      unsigned int  num_idx;
 
 
-      af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
-      if ( glyph_index == 0 )
+      /* reject input that maps to more than a single glyph */
+      p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+      if ( num_idx > 1 )
         continue;
 
-      if ( FT_Get_Advance( face, glyph_index,
-                           FT_LOAD_NO_SCALE         |
-                           FT_LOAD_NO_HINTING       |
-                           FT_LOAD_IGNORE_TRANSFORM,
-                           &advance ) )
+      glyph_index = af_shaper_get_elem( &metrics->root,
+                                        shaper_buf,
+                                        0,
+                                        &advance,
+                                        NULL );
+      if ( !glyph_index )
         continue;
 
       if ( started )
@@ -853,6 +987,8 @@
       }
     }
 
+    af_shaper_buf_destroy( face, shaper_buf );
+
     metrics->root.digits_have_same_width = same_width;
   }
 
@@ -940,7 +1076,7 @@
         FT_UInt  ppem;
 
 
-        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
+        scaled    = FT_MulFix( blue->shoot.org, scale );
         ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
         limit     = metrics->root.globals->increase_x_height;
         threshold = 40;
@@ -966,18 +1102,52 @@
 #endif
           if ( dim == AF_DIMENSION_VERT )
           {
-            scale = FT_MulDiv( scale, fitted, scaled );
+            FT_Pos    max_height;
+            FT_Pos    dist;
+            FT_Fixed  new_scale;
 
-            FT_TRACE5((
-              "af_latin_metrics_scale_dim:"
-              " x height alignment (style `%s'):\n"
-              "                           "
-              " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
-              "\n",
-              af_style_names[metrics->root.style_class->style],
-              axis->org_scale / 65536.0,
-              scale / 65536.0,
-              ( fitted - scaled ) * 100 / scaled ));
+
+            new_scale = FT_MulDiv( scale, fitted, scaled );
+
+            /* the scaling should not change the result by more than two pixels */
+            max_height = metrics->units_per_em;
+
+            for ( nn = 0; nn < Axis->blue_count; nn++ )
+            {
+              max_height = FT_MAX( max_height, Axis->blues[nn].ascender );
+              max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
+            }
+
+            dist  = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
+            dist &= ~127;
+
+            if ( dist == 0 )
+            {
+              FT_TRACE5((
+                "af_latin_metrics_scale_dim:"
+                " x height alignment (style `%s'):\n"
+                "                           "
+                " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
+                "\n",
+                af_style_names[metrics->root.style_class->style],
+                scale / 65536.0,
+                new_scale / 65536.0,
+                ( fitted - scaled ) * 100 / scaled ));
+
+              scale = new_scale;
+            }
+#ifdef FT_DEBUG_LEVEL_TRACE
+            else
+            {
+              FT_TRACE5((
+                "af_latin_metrics_scale_dim:"
+                " x height alignment (style `%s'):\n"
+                "                           "
+                " excessive vertical scaling abandoned\n"
+                "\n",
+                af_style_names[metrics->root.style_class->style] ));
+            }
+#endif
           }
         }
       }
@@ -1031,8 +1201,11 @@
 
     if ( dim == AF_DIMENSION_VERT )
     {
-      FT_TRACE5(( "blue zones (style `%s')\n",
-                  af_style_names[metrics->root.style_class->style] ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+      if ( axis->blue_count )
+        FT_TRACE5(( "blue zones (style `%s')\n",
+                    af_style_names[metrics->root.style_class->style] ));
+#endif
 
       /* scale the blue zones */
       for ( nn = 0; nn < axis->blue_count; nn++ )
@@ -1105,21 +1278,63 @@
 #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)" ));
         }
       }
+
+      /* use sub-top blue zone only if it doesn't overlap with */
+      /* another (non-sup-top) blue zone; otherwise, the       */
+      /* effect would be similar to a neutral blue zone, which */
+      /* is not desired here                                   */
+      for ( nn = 0; nn < axis->blue_count; nn++ )
+      {
+        AF_LatinBlue  blue = &axis->blues[nn];
+        FT_UInt       i;
+
+
+        if ( !( blue->flags & AF_LATIN_BLUE_SUB_TOP ) )
+          continue;
+        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+          continue;
+
+        for ( i = 0; i < axis->blue_count; i++ )
+        {
+          AF_LatinBlue  b = &axis->blues[i];
+
+
+          if ( b->flags & AF_LATIN_BLUE_SUB_TOP )
+            continue;
+          if ( !( b->flags & AF_LATIN_BLUE_ACTIVE ) )
+            continue;
+
+          if ( b->ref.fit <= blue->shoot.fit &&
+               b->shoot.fit >= blue->ref.fit )
+          {
+            blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+            break;
+          }
+        }
+      }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+      for ( nn = 0; nn < axis->blue_count; nn++ )
+      {
+        AF_LatinBlue  blue = &axis->blues[nn];
+
+
+        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)" ));
+      }
+#endif
     }
   }
 
@@ -1139,6 +1354,22 @@
   }
 
 
+  /* Extract standard_width from writing system/script specific */
+  /* metrics class.                                             */
+
+  FT_LOCAL_DEF( void )
+  af_latin_get_standard_widths( AF_LatinMetrics  metrics,
+                                FT_Pos*          stdHW,
+                                FT_Pos*          stdVW )
+  {
+    if ( stdHW )
+      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+    if ( stdVW )
+      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -1154,14 +1385,17 @@
   af_latin_hints_compute_segments( AF_GlyphHints  hints,
                                    AF_Dimension   dim )
   {
-    AF_AxisHints   axis          = &hints->axis[dim];
-    FT_Memory      memory        = hints->memory;
-    FT_Error       error         = FT_Err_Ok;
-    AF_Segment     segment       = NULL;
-    AF_SegmentRec  seg0;
-    AF_Point*      contour       = hints->contours;
-    AF_Point*      contour_limit = contour + hints->num_contours;
-    AF_Direction   major_dir, segment_dir;
+    AF_LatinMetrics  metrics       = (AF_LatinMetrics)hints->metrics;
+    AF_AxisHints     axis          = &hints->axis[dim];
+    FT_Memory        memory        = hints->memory;
+    FT_Error         error         = FT_Err_Ok;
+    AF_Segment       segment       = NULL;
+    AF_SegmentRec    seg0;
+    AF_Point*        contour       = hints->contours;
+    AF_Point*        contour_limit = contour + hints->num_contours;
+    AF_Direction     major_dir, segment_dir;
+
+    FT_Pos  flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
 
 
     FT_ZERO( &seg0 );
@@ -1202,16 +1436,35 @@
     /* do each contour separately */
     for ( ; contour < contour_limit; contour++ )
     {
-      AF_Point  point   =  contour[0];
-      AF_Point  last    =  point->prev;
-      int       on_edge =  0;
-      FT_Pos    min_pos =  32000;  /* minimum segment pos != min_coord */
-      FT_Pos    max_pos = -32000;  /* maximum segment pos != max_coord */
-      FT_Bool   passed;
+      AF_Point  point   = contour[0];
+      AF_Point  last    = point->prev;
+      int       on_edge = 0;
 
+      /* we call values measured along a segment (point->v)    */
+      /* `coordinates', and values orthogonal to it (point->u) */
+      /* `positions'                                           */
+      FT_Pos     min_pos      =  32000;
+      FT_Pos     max_pos      = -32000;
+      FT_Pos     min_coord    =  32000;
+      FT_Pos     max_coord    = -32000;
+      FT_UShort  min_flags    =  AF_FLAG_NONE;
+      FT_UShort  max_flags    =  AF_FLAG_NONE;
+      FT_Pos     min_on_coord =  32000;
+      FT_Pos     max_on_coord = -32000;
 
-      if ( point == last )  /* skip singletons -- just in case */
-        continue;
+      FT_Bool  passed;
+
+      AF_Segment  prev_segment = NULL;
+
+      FT_Pos     prev_min_pos      = min_pos;
+      FT_Pos     prev_max_pos      = max_pos;
+      FT_Pos     prev_min_coord    = min_coord;
+      FT_Pos     prev_max_coord    = max_coord;
+      FT_UShort  prev_min_flags    = min_flags;
+      FT_UShort  prev_max_flags    = max_flags;
+      FT_Pos     prev_min_on_coord = min_on_coord;
+      FT_Pos     prev_max_on_coord = max_on_coord;
+
 
       if ( FT_ABS( last->out_dir )  == major_dir &&
            FT_ABS( point->out_dir ) == major_dir )
@@ -1242,40 +1495,182 @@
 
         if ( on_edge )
         {
+          /* get minimum and maximum position */
           u = point->u;
           if ( u < min_pos )
             min_pos = u;
           if ( u > max_pos )
             max_pos = u;
 
+          /* get minimum and maximum coordinate together with flags */
+          v = point->v;
+          if ( v < min_coord )
+          {
+            min_coord = v;
+            min_flags = point->flags;
+          }
+          if ( v > max_coord )
+          {
+            max_coord = v;
+            max_flags = point->flags;
+          }
+
+          /* get minimum and maximum coordinate of `on' points */
+          if ( !( point->flags & AF_FLAG_CONTROL ) )
+          {
+            v = point->v;
+            if ( v < min_on_coord )
+              min_on_coord = v;
+            if ( v > max_on_coord )
+              max_on_coord = v;
+          }
+
           if ( point->out_dir != segment_dir || point == last )
           {
-            /* we are just leaving an edge; record a new segment! */
-            segment->last = point;
-            segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+            /* check whether the new segment's start point is identical to */
+            /* the previous segment's end point; for example, this might   */
+            /* happen for spikes                                           */
 
-            /* a segment is round if either its first or last point */
-            /* is a control point                                   */
-            if ( ( segment->first->flags | point->flags ) &
-                 AF_FLAG_CONTROL                          )
-              segment->flags |= AF_EDGE_ROUND;
+            if ( !prev_segment || segment->first != prev_segment->last )
+            {
+              /* points are different: we are just leaving an edge, thus */
+              /* record a new segment                                    */
 
-            /* compute segment size */
-            min_pos = max_pos = point->v;
+              segment->last  = point;
+              segment->pos   = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+              segment->delta = (FT_Short)( ( max_pos - min_pos ) >> 1 );
 
-            v = segment->first->v;
-            if ( v < min_pos )
-              min_pos = v;
-            if ( v > max_pos )
-              max_pos = v;
+              /* a segment is round if either its first or last point */
+              /* is a control point, and the length of the on points  */
+              /* inbetween doesn't exceed a heuristic limit           */
+              if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                   ( max_on_coord - min_on_coord ) < flat_threshold )
+                segment->flags |= AF_EDGE_ROUND;
 
-            segment->min_coord = (FT_Short)min_pos;
-            segment->max_coord = (FT_Short)max_pos;
-            segment->height    = (FT_Short)( segment->max_coord -
-                                             segment->min_coord );
+              segment->min_coord = (FT_Short)min_coord;
+              segment->max_coord = (FT_Short)max_coord;
+              segment->height    = segment->max_coord - segment->min_coord;
+
+              prev_segment      = segment;
+              prev_min_pos      = min_pos;
+              prev_max_pos      = max_pos;
+              prev_min_coord    = min_coord;
+              prev_max_coord    = max_coord;
+              prev_min_flags    = min_flags;
+              prev_max_flags    = max_flags;
+              prev_min_on_coord = min_on_coord;
+              prev_max_on_coord = max_on_coord;
+            }
+            else
+            {
+              /* points are the same: we don't create a new segment but */
+              /* merge the current segment with the previous one        */
+
+              if ( prev_segment->last->in_dir == point->in_dir )
+              {
+                /* we have identical directions (this can happen for       */
+                /* degenerate outlines that move zig-zag along the main    */
+                /* axis without changing the coordinate value of the other */
+                /* axis, and where the segments have just been merged):    */
+                /* unify segments                                          */
+
+                /* update constraints */
+
+                if ( prev_min_pos < min_pos )
+                  min_pos = prev_min_pos;
+                if ( prev_max_pos > max_pos )
+                  max_pos = prev_max_pos;
+
+                if ( prev_min_coord < min_coord )
+                {
+                  min_coord = prev_min_coord;
+                  min_flags = prev_min_flags;
+                }
+                if ( prev_max_coord > max_coord )
+                {
+                  max_coord = prev_max_coord;
+                  max_flags = prev_max_flags;
+                }
+
+                if ( prev_min_on_coord < min_on_coord )
+                  min_on_coord = prev_min_on_coord;
+                if ( prev_max_on_coord > max_on_coord )
+                  max_on_coord = prev_max_on_coord;
+
+                prev_segment->last = point;
+                prev_segment->pos  = (FT_Short)( ( min_pos +
+                                                   max_pos ) >> 1 );
+
+                if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                     ( max_on_coord - min_on_coord ) < flat_threshold )
+                  prev_segment->flags |= AF_EDGE_ROUND;
+                else
+                  prev_segment->flags &= ~AF_EDGE_ROUND;
+
+                prev_segment->min_coord = (FT_Short)min_coord;
+                prev_segment->max_coord = (FT_Short)max_coord;
+                prev_segment->height    = prev_segment->max_coord -
+                                          prev_segment->min_coord;
+              }
+              else
+              {
+                /* we have different directions; use the properties of the */
+                /* longer segment and discard the other one                */
+
+                if ( FT_ABS( prev_max_coord - prev_min_coord ) >
+                     FT_ABS( max_coord - min_coord ) )
+                {
+                  /* discard current segment */
+
+                  if ( min_pos < prev_min_pos )
+                    prev_min_pos = min_pos;
+                  if ( max_pos > prev_max_pos )
+                    prev_max_pos = max_pos;
+
+                  prev_segment->last = point;
+                  prev_segment->pos  = (FT_Short)( ( prev_min_pos +
+                                                     prev_max_pos ) >> 1 );
+                }
+                else
+                {
+                  /* discard previous segment */
+
+                  if ( prev_min_pos < min_pos )
+                    min_pos = prev_min_pos;
+                  if ( prev_max_pos > max_pos )
+                    max_pos = prev_max_pos;
+
+                  segment->last = point;
+                  segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+
+                  if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                       ( max_on_coord - min_on_coord ) < flat_threshold )
+                    segment->flags |= AF_EDGE_ROUND;
+
+                  segment->min_coord = (FT_Short)min_coord;
+                  segment->max_coord = (FT_Short)max_coord;
+                  segment->height    = segment->max_coord -
+                                       segment->min_coord;
+
+                  *prev_segment = *segment;
+
+                  prev_min_pos      = min_pos;
+                  prev_max_pos      = max_pos;
+                  prev_min_coord    = min_coord;
+                  prev_max_coord    = max_coord;
+                  prev_min_flags    = min_flags;
+                  prev_max_flags    = max_flags;
+                  prev_min_on_coord = min_on_coord;
+                  prev_max_on_coord = max_on_coord;
+                }
+              }
+
+              axis->num_segments--;
+            }
 
             on_edge = 0;
             segment = NULL;
+
             /* fall through */
           }
         }
@@ -1288,22 +1683,63 @@
           passed = 1;
         }
 
-        if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )
+        /* if we are not on an edge, check whether the major direction */
+        /* coincides with the current point's `out' direction, or      */
+        /* whether we have a single-point contour                      */
+        if ( !on_edge                                  &&
+             ( FT_ABS( point->out_dir ) == major_dir ||
+               point == point->prev                  ) )
         {
           /* this is the start of a new segment! */
           segment_dir = (AF_Direction)point->out_dir;
 
-          /* clear all segment fields */
           error = af_axis_hints_new_segment( axis, memory, &segment );
           if ( error )
             goto Exit;
 
-          segment[0]        = seg0;
-          segment->dir      = (FT_Char)segment_dir;
-          min_pos = max_pos = point->u;
-          segment->first    = point;
-          segment->last     = point;
-          on_edge           = 1;
+          /* clear all segment fields */
+          segment[0] = seg0;
+
+          segment->dir   = (FT_Char)segment_dir;
+          segment->first = point;
+          segment->last  = point;
+
+          /* `af_axis_hints_new_segment' reallocates memory,    */
+          /* thus we have to refresh the `prev_segment' pointer */
+          if ( prev_segment )
+            prev_segment = segment - 1;
+
+          min_pos   = max_pos   = point->u;
+          min_coord = max_coord = point->v;
+          min_flags = max_flags = point->flags;
+
+          if ( point->flags & AF_FLAG_CONTROL )
+          {
+            min_on_coord =  32000;
+            max_on_coord = -32000;
+          }
+          else
+            min_on_coord = max_on_coord = point->v;
+
+          on_edge = 1;
+
+          if ( point == point->prev )
+          {
+            /* we have a one-point segment: this is a one-point */
+            /* contour with `in' and `out' direction set to     */
+            /* AF_DIR_NONE                                      */
+            segment->pos = (FT_Short)min_pos;
+
+            if (point->flags & AF_FLAG_CONTROL)
+              segment->flags |= AF_EDGE_ROUND;
+
+            segment->min_coord = (FT_Short)point->v;
+            segment->max_coord = (FT_Short)point->v;
+            segment->height = 0;
+
+            on_edge = 0;
+            segment = NULL;
+          }
         }
 
         point = point->next;
@@ -1327,9 +1763,6 @@
         FT_Pos    last_v  = last->v;
 
 
-        if ( first == last )
-          continue;
-
         if ( first_v < last_v )
         {
           AF_Point  p;
@@ -1405,9 +1838,7 @@
     /* now compare each segment to the others */
     for ( seg1 = segments; seg1 < segment_limit; seg1++ )
     {
-      /* the fake segments are introduced to hint the metrics -- */
-      /* we must never link them to anything                     */
-      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+      if ( seg1->dir != axis->major_dir )
         continue;
 
       /* search for stems having opposite directions, */
@@ -1520,6 +1951,12 @@
     FT_Memory     memory = hints->memory;
     AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
 
+    AF_StyleClass   style_class  = hints->metrics->style_class;
+    AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
+                                     [style_class->script];
+
+    FT_Bool  top_to_bottom_hinting = 0;
+
     AF_Segment    segments      = axis->segments;
     AF_Segment    segment_limit = segments + axis->num_segments;
     AF_Segment    seg;
@@ -1530,6 +1967,7 @@
     FT_Fixed      scale;
     FT_Pos        edge_distance_threshold;
     FT_Pos        segment_length_threshold;
+    FT_Pos        segment_width_threshold;
 
 
     axis->num_edges = 0;
@@ -1542,15 +1980,24 @@
                                           : AF_DIR_RIGHT;
 #endif
 
+    if ( dim == AF_DIMENSION_VERT )
+      top_to_bottom_hinting = script_class->top_to_bottom_hinting;
+
     /*
      *  We ignore all segments that are less than 1 pixel in length
      *  to avoid many problems with serif fonts.  We compute the
      *  corresponding threshold in font units.
      */
     if ( dim == AF_DIMENSION_HORZ )
-        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
+      segment_length_threshold = FT_DivFix( 64, hints->y_scale );
     else
-        segment_length_threshold = 0;
+      segment_length_threshold = 0;
+
+    /*
+     *  Similarly, we ignore segments that have a width delta
+     *  larger than 0.5px (i.e., a width larger than 1px).
+     */
+    segment_width_threshold = FT_DivFix( 32, scale );
 
     /*********************************************************************/
     /*                                                                   */
@@ -1583,7 +2030,11 @@
       FT_Int   ee;
 
 
-      if ( seg->height < segment_length_threshold )
+      /* ignore too short segments, too wide ones, and, in this loop, */
+      /* one-point segments without a direction                       */
+      if ( seg->height < segment_length_threshold ||
+           seg->delta > segment_width_threshold   ||
+           seg->dir == AF_DIR_NONE                )
         continue;
 
       /* A special case for serif edges: If they are smaller than */
@@ -1619,6 +2070,7 @@
         /* sort according to the position    */
         error = af_axis_hints_new_edge( axis, seg->pos,
                                         (AF_Direction)seg->dir,
+                                        top_to_bottom_hinting,
                                         memory, &edge );
         if ( error )
           goto Exit;
@@ -1644,6 +2096,44 @@
       }
     }
 
+    /* we loop again over all segments to catch one-point segments   */
+    /* without a direction: if possible, link them to existing edges */
+    for ( seg = segments; seg < segment_limit; seg++ )
+    {
+      AF_Edge  found = NULL;
+      FT_Int   ee;
+
+
+      if ( seg->dir != AF_DIR_NONE )
+        continue;
+
+      /* look for an edge corresponding to the segment */
+      for ( ee = 0; ee < axis->num_edges; ee++ )
+      {
+        AF_Edge  edge = axis->edges + ee;
+        FT_Pos   dist;
+
+
+        dist = seg->pos - edge->fpos;
+        if ( dist < 0 )
+          dist = -dist;
+
+        if ( dist < edge_distance_threshold )
+        {
+          found = edge;
+          break;
+        }
+      }
+
+      /* one-point segments without a match are ignored */
+      if ( found )
+      {
+        seg->edge_next         = found->first;
+        found->last->edge_next = seg;
+        found->last            = seg;
+      }
+    }
+
 
     /******************************************************************/
     /*                                                                */
@@ -1794,7 +2284,7 @@
         /*      Example: the `c' in cour.pfa at size 13     */
 
         if ( edge->serif && edge->link )
-          edge->serif = 0;
+          edge->serif = NULL;
       }
     }
 
@@ -1828,7 +2318,7 @@
 
   /* Compute all edges which lie within blue zones. */
 
-  FT_LOCAL_DEF( void )
+  static void
   af_latin_hints_compute_blue_edges( AF_GlyphHints    hints,
                                      AF_LatinMetrics  metrics )
   {
@@ -1874,7 +2364,8 @@
         /* the major direction) -- this assumes the TrueType convention  */
         /* for the orientation of contours                               */
         is_top_blue =
-          (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+          (FT_Byte)( ( blue->flags & ( AF_LATIN_BLUE_TOP     |
+                                       AF_LATIN_BLUE_SUB_TOP ) ) != 0 );
         is_neutral_blue =
           (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
         is_major_dir =
@@ -1998,11 +2489,20 @@
     /*
      *  In `light' hinting mode we disable horizontal hinting completely.
      *  We also do it if the face is italic.
+     *
+     *  However, if warping is enabled (which only works in `light' hinting
+     *  mode), advance widths get adjusted, too.
      */
     if ( mode == FT_RENDER_MODE_LIGHT                      ||
          ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
       scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
 
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    /* get (global) warper flag */
+    if ( !metrics->root.globals->module->warping )
+      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
@@ -2023,13 +2523,13 @@
 
   static FT_Pos
   af_latin_snap_width( AF_Width  widths,
-                       FT_Int    count,
+                       FT_UInt   count,
                        FT_Pos    width )
   {
-    int     n;
-    FT_Pos  best      = 64 + 32 + 2;
-    FT_Pos  reference = width;
-    FT_Pos  scaled;
+    FT_UInt  n;
+    FT_Pos   best      = 64 + 32 + 2;
+    FT_Pos   reference = width;
+    FT_Pos   scaled;
 
 
     for ( n = 0; n < count; n++ )
@@ -2074,8 +2574,9 @@
   af_latin_compute_stem_width( AF_GlyphHints  hints,
                                AF_Dimension   dim,
                                FT_Pos         width,
-                               AF_Edge_Flags  base_flags,
-                               AF_Edge_Flags  stem_flags )
+                               FT_Pos         base_delta,
+                               FT_UInt        base_flags,
+                               FT_UInt        stem_flags )
   {
     AF_LatinMetrics  metrics  = (AF_LatinMetrics)hints->metrics;
     AF_LatinAxis     axis     = &metrics->axis[dim];
@@ -2151,7 +2652,39 @@
             dist += delta;
         }
         else
-          dist = ( dist + 32 ) & ~63;
+        {
+          /* A stem's end position depends on two values: the start        */
+          /* position and the stem length.  The former gets usually        */
+          /* rounded to the grid, while the latter gets rounded also if it */
+          /* exceeds a certain length (see below in this function).  This  */
+          /* `double rounding' can lead to a great difference to the       */
+          /* original, unhinted position; this normally doesn't matter for */
+          /* large PPEM values, but for small sizes it can easily make     */
+          /* outlines collide.  For this reason, we adjust the stem length */
+          /* by a small amount depending on the PPEM value in case the     */
+          /* former and latter rounding both point into the same           */
+          /* direction.                                                    */
+
+          FT_Pos  bdelta = 0;
+
+
+          if ( ( ( width > 0 ) && ( base_delta > 0 ) ) ||
+               ( ( width < 0 ) && ( base_delta < 0 ) ) )
+          {
+            FT_UInt  ppem = metrics->root.scaler.face->size->metrics.x_ppem;
+
+
+            if ( ppem < 10 )
+              bdelta = base_delta;
+            else if ( ppem < 30 )
+              bdelta = ( base_delta * (FT_Pos)( 30 - ppem ) ) / 20;
+
+            if ( bdelta < 0 )
+              bdelta = -bdelta;
+          }
+
+          dist = ( dist - bdelta + 32 ) & ~63;
+        }
       }
     }
     else
@@ -2240,12 +2773,17 @@
                               AF_Edge        base_edge,
                               AF_Edge        stem_edge )
   {
-    FT_Pos  dist = stem_edge->opos - base_edge->opos;
+    FT_Pos  dist, base_delta;
+    FT_Pos  fitted_width;
 
-    FT_Pos  fitted_width = af_latin_compute_stem_width(
-                             hints, dim, dist,
-                             (AF_Edge_Flags)base_edge->flags,
-                             (AF_Edge_Flags)stem_edge->flags );
+
+    dist       = stem_edge->opos - base_edge->opos;
+    base_delta = base_edge->pos - base_edge->opos;
+
+    fitted_width = af_latin_compute_stem_width( hints, dim,
+                                                dist, base_delta,
+                                                base_edge->flags,
+                                                stem_edge->flags );
 
 
     stem_edge->pos = base_edge->pos + fitted_width;
@@ -2284,7 +2822,7 @@
 
   /* The main grid-fitting routine. */
 
-  FT_LOCAL_DEF( void )
+  static void
   af_latin_hint_edges( AF_GlyphHints  hints,
                        AF_Dimension   dim )
   {
@@ -2296,8 +2834,14 @@
     AF_Edge       anchor     = NULL;
     FT_Int        has_serifs = 0;
 
+    AF_StyleClass   style_class  = hints->metrics->style_class;
+    AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
+                                     [style_class->script];
+
+    FT_Bool  top_to_bottom_hinting = 0;
+
 #ifdef FT_DEBUG_LEVEL_TRACE
-    FT_UInt       num_actions = 0;
+    FT_UInt  num_actions = 0;
 #endif
 
 
@@ -2305,6 +2849,9 @@
                 dim == AF_DIMENSION_VERT ? "horizontal" : "vertical",
                 af_style_names[hints->metrics->style_class->style] ));
 
+    if ( dim == AF_DIMENSION_VERT )
+      top_to_bottom_hinting = script_class->top_to_bottom_hinting;
+
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
 
@@ -2337,7 +2884,7 @@
           FT_Byte  neutral2 = edge2->flags & AF_EDGE_NEUTRAL;
 
 
-          if ( ( neutral && neutral2 ) || neutral2 )
+          if ( neutral2 )
           {
             edge2->blue_edge = NULL;
             edge2->flags    &= ~AF_EDGE_NEUTRAL;
@@ -2440,10 +2987,10 @@
 
 
         org_len = edge2->opos - edge->opos;
-        cur_len = af_latin_compute_stem_width(
-                    hints, dim, org_len,
-                    (AF_Edge_Flags)edge->flags,
-                    (AF_Edge_Flags)edge2->flags );
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
+                                               edge->flags,
+                                               edge2->flags );
 
         /* some voodoo to specially round edges for small stem widths; */
         /* the idea is to align the center of a stem, then shifting    */
@@ -2510,10 +3057,10 @@
         org_len    = edge2->opos - edge->opos;
         org_center = org_pos + ( org_len >> 1 );
 
-        cur_len = af_latin_compute_stem_width(
-                    hints, dim, org_len,
-                    (AF_Edge_Flags)edge->flags,
-                    (AF_Edge_Flags)edge2->flags );
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
+                                               edge->flags,
+                                               edge2->flags );
 
         if ( edge2->flags & AF_EDGE_DONE )
         {
@@ -2571,10 +3118,10 @@
           org_len    = edge2->opos - edge->opos;
           org_center = org_pos + ( org_len >> 1 );
 
-          cur_len    = af_latin_compute_stem_width(
-                         hints, dim, org_len,
-                         (AF_Edge_Flags)edge->flags,
-                         (AF_Edge_Flags)edge2->flags );
+          cur_len    = af_latin_compute_stem_width( hints, dim,
+                                                    org_len, 0,
+                                                    edge->flags,
+                                                    edge2->flags );
 
           cur_pos1 = FT_PIX_ROUND( org_pos );
           delta1   = cur_pos1 + ( cur_len >> 1 ) - org_center;
@@ -2603,16 +3150,25 @@
         edge->flags  |= AF_EDGE_DONE;
         edge2->flags |= AF_EDGE_DONE;
 
-        if ( edge > edges && edge->pos < edge[-1].pos )
+        if ( edge > edges                                             &&
+             ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos )
+                                     : ( edge->pos < edge[-1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[-1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
 
-          edge->pos = edge[-1].pos;
+            edge->pos = edge[-1].pos;
+          }
         }
       }
     }
@@ -2764,29 +3320,46 @@
 #endif
         edge->flags |= AF_EDGE_DONE;
 
-        if ( edge > edges && edge->pos < edge[-1].pos )
+        if ( edge > edges                                             &&
+             ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos )
+                                     : ( edge->pos < edge[-1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[-1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
-          edge->pos = edge[-1].pos;
+            edge->pos = edge[-1].pos;
+          }
         }
 
-        if ( edge + 1 < edge_limit        &&
-             edge[1].flags & AF_EDGE_DONE &&
-             edge->pos > edge[1].pos      )
+        if ( edge + 1 < edge_limit                                   &&
+             edge[1].flags & AF_EDGE_DONE                            &&
+             ( top_to_bottom_hinting ? ( edge->pos < edge[1].pos )
+                                     : ( edge->pos > edge[1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
 
-          edge->pos = edge[1].pos;
+            edge->pos = edge[1].pos;
+          }
         }
       }
     }
@@ -2802,7 +3375,8 @@
   /* Apply the complete hinting algorithm to a latin glyph. */
 
   static FT_Error
-  af_latin_hints_apply( AF_GlyphHints    hints,
+  af_latin_hints_apply( FT_UInt          glyph_index,
+                        AF_GlyphHints    hints,
                         FT_Outline*      outline,
                         AF_LatinMetrics  metrics )
   {
@@ -2818,8 +3392,9 @@
 
     /* analyze glyph outline */
 #ifdef AF_CONFIG_OPTION_USE_WARPER
-    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
-         AF_HINTS_DO_HORIZONTAL( hints )                          )
+    if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+           AF_HINTS_DO_WARP( hints )                                ) ||
+         AF_HINTS_DO_HORIZONTAL( hints )                              )
 #else
     if ( AF_HINTS_DO_HORIZONTAL( hints ) )
 #endif
@@ -2843,7 +3418,9 @@
       if ( error )
         goto Exit;
 
-      af_latin_hints_compute_blue_edges( hints, metrics );
+      /* apply blue zones to base characters only */
+      if ( !( metrics->root.globals->glyph_styles[glyph_index] & AF_NONBASE ) )
+        af_latin_hints_compute_blue_edges( hints, metrics );
     }
 
     /* grid-fit the outline */
@@ -2851,7 +3428,8 @@
     {
 #ifdef AF_CONFIG_OPTION_USE_WARPER
       if ( dim == AF_DIMENSION_HORZ                                 &&
-           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
+           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+           AF_HINTS_DO_WARP( hints )                                )
       {
         AF_WarperRec  warper;
         FT_Fixed      scale;
@@ -2864,7 +3442,7 @@
                                   scale, delta );
         continue;
       }
-#endif
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
 
       if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
            ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
@@ -2902,6 +3480,7 @@
     (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,
     (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths,
 
     (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,
     (AF_WritingSystem_ApplyHintsFunc)  af_latin_hints_apply
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index 2c0bfca..fe6bbd8 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter hinting routines for latin writing system                */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009, 2011-2014 by                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFLATIN_H__
-#define __AFLATIN_H__
+#ifndef AFLATIN_H_
+#define AFLATIN_H_
 
 #include "afhints.h"
 
@@ -53,6 +53,8 @@
 
 #define AF_LATIN_IS_TOP_BLUE( b ) \
           ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
+#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
 #define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
           ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
 #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
@@ -63,21 +65,21 @@
 #define AF_LATIN_MAX_WIDTHS  16
 
 
-  enum
-  {
-    AF_LATIN_BLUE_ACTIVE     = 1 << 0, /* set if zone height is <= 3/4px   */
-    AF_LATIN_BLUE_TOP        = 1 << 1, /* set if we have a top blue zone   */
-    AF_LATIN_BLUE_NEUTRAL    = 1 << 2, /* set if we have neutral blue zone */
-    AF_LATIN_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment        */
-                                       /* optimization                     */
-    AF_LATIN_BLUE_FLAG_MAX
-  };
+#define AF_LATIN_BLUE_ACTIVE      ( 1U << 0 ) /* zone height is <= 3/4px   */
+#define AF_LATIN_BLUE_TOP         ( 1U << 1 ) /* we have a top blue zone   */
+#define AF_LATIN_BLUE_SUB_TOP     ( 1U << 2 ) /* we have a subscript top   */
+                                              /* blue zone                 */
+#define AF_LATIN_BLUE_NEUTRAL     ( 1U << 3 ) /* we have neutral blue zone */
+#define AF_LATIN_BLUE_ADJUSTMENT  ( 1U << 4 ) /* used for scale adjustment */
+                                              /* optimization              */
 
 
   typedef struct  AF_LatinBlueRec_
   {
     AF_WidthRec  ref;
     AF_WidthRec  shoot;
+    FT_Pos       ascender;
+    FT_Pos       descender;
     FT_UInt      flags;
 
   } AF_LatinBlueRec, *AF_LatinBlue;
@@ -138,15 +140,11 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  enum
-  {
-    AF_LATIN_HINTS_HORZ_SNAP   = 1 << 0, /* enable stem width snapping  */
-    AF_LATIN_HINTS_VERT_SNAP   = 1 << 1, /* enable stem height snapping */
-    AF_LATIN_HINTS_STEM_ADJUST = 1 << 2, /* enable stem width/height    */
-                                         /* adjustment                  */
-    AF_LATIN_HINTS_MONO        = 1 << 3  /* indicate monochrome         */
-                                         /* rendering                   */
-  };
+#define AF_LATIN_HINTS_HORZ_SNAP    ( 1U << 0 ) /* stem width snapping  */
+#define AF_LATIN_HINTS_VERT_SNAP    ( 1U << 1 ) /* stem height snapping */
+#define AF_LATIN_HINTS_STEM_ADJUST  ( 1U << 2 ) /* stem width/height    */
+                                                /* adjustment           */
+#define AF_LATIN_HINTS_MONO         ( 1U << 3 ) /* monochrome rendering */
 
 
 #define AF_LATIN_HINTS_DO_HORZ_SNAP( h )             \
@@ -190,7 +188,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFLATIN_H__ */
+#endif /* AFLATIN_H_ */
 
 
 /* END */
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index 930fa98..5db4a41 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -1,10 +1,15 @@
+/* ATTENTION: This file doesn't compile.  It is only here as a reference */
+/*            of an alternative latin hinting algorithm that was always  */
+/*            marked as experimental.                                    */
+
+
 /***************************************************************************/
 /*                                                                         */
 /*  aflatin2.c                                                             */
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin writing system (body).        */
 /*                                                                         */
-/*  Copyright 2003-2013 by                                                 */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -693,6 +698,22 @@
   }
 
 
+  /* Extract standard_width from writing system/script specific */
+  /* metrics class.                                             */
+
+  FT_LOCAL_DEF( void )
+  af_latin2_get_standard_widths( AF_LatinMetrics  metrics,
+                                 FT_Pos*          stdHW,
+                                 FT_Pos*          stdVW )
+  {
+    if ( stdHW )
+      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+    if ( stdVW )
+      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -835,8 +856,8 @@
         {
           AF_Point  pt   = first;
           AF_Point  last = point;
-          AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
-          AF_Flags  f1;
+          FT_UInt   f0   = pt->flags & AF_FLAG_CONTROL;
+          FT_UInt   f1;
 
 
           segment->flags &= ~AF_EDGE_ROUND;
@@ -844,7 +865,7 @@
           for ( ; pt != last; f0 = f1 )
           {
             pt = pt->next;
-            f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
+            f1 = pt->flags & AF_FLAG_CONTROL;
 
             if ( !f0 && !f1 )
               break;
@@ -890,9 +911,6 @@
         FT_Pos    last_v  = last->v;
 
 
-        if ( first == last )
-          continue;
-
         if ( first_v < last_v )
         {
           p = first->prev;
@@ -984,7 +1002,7 @@
 #ifdef AF_SORT_SEGMENTS
     for ( seg1 = segments; seg1 < segment_mid; seg1++ )
     {
-      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+      if ( seg1->dir != axis->major_dir )
         continue;
 
       for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
@@ -992,9 +1010,7 @@
     /* now compare each segment to the others */
     for ( seg1 = segments; seg1 < segment_limit; seg1++ )
     {
-      /* the fake segments are introduced to hint the metrics -- */
-      /* we must never link them to anything                     */
-      if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+      if ( seg1->dir != axis->major_dir )
         continue;
 
       for ( seg2 = segments; seg2 < segment_limit; seg2++ )
@@ -1053,7 +1069,7 @@
       {
         if ( seg2->link != seg1 )
         {
-          seg1->link  = 0;
+          seg1->link  = NULL;
           seg1->serif = seg2->link;
         }
       }
@@ -1133,7 +1149,7 @@
 
     for ( seg = segments; seg < segment_limit; seg++ )
     {
-      AF_Edge  found = 0;
+      AF_Edge  found = NULL;
       FT_Int   ee;
 
 
@@ -1184,7 +1200,7 @@
 
         /* insert a new edge in the list and */
         /* sort according to the position    */
-        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
+        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0,
                                         memory, &edge );
         if ( error )
           goto Exit;
@@ -1194,9 +1210,10 @@
 
         edge->first    = seg;
         edge->last     = seg;
-        edge->fpos     = seg->pos;
         edge->dir      = seg->dir;
-        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
+        edge->fpos     = seg->pos;
+        edge->opos     = FT_MulFix( seg->pos, scale );
+        edge->pos      = edge->opos;
         seg->edge_next = seg;
       }
       else
@@ -1359,7 +1376,7 @@
         /*      Example: the `c' in cour.pfa at size 13     */
 
         if ( edge->serif && edge->link )
-          edge->serif = 0;
+          edge->serif = NULL;
       }
     }
 
@@ -1386,7 +1403,7 @@
   }
 
 
-  FT_LOCAL_DEF( void )
+  static void
   af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
                                       AF_LatinMetrics  metrics )
   {
@@ -1517,9 +1534,7 @@
 
 #if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
-    {
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
-    }
 #endif
 
     scaler_flags = hints->scaler_flags;
@@ -1556,6 +1571,12 @@
          ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
       scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
 
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    /* get (global) warper flag */
+    if ( !metrics->root.globals->module->warping )
+      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
@@ -1576,13 +1597,13 @@
 
   static FT_Pos
   af_latin2_snap_width( AF_Width  widths,
-                        FT_Int    count,
+                        FT_UInt   count,
                         FT_Pos    width )
   {
-    int     n;
-    FT_Pos  best      = 64 + 32 + 2;
-    FT_Pos  reference = width;
-    FT_Pos  scaled;
+    FT_UInt  n;
+    FT_Pos   best      = 64 + 32 + 2;
+    FT_Pos   reference = width;
+    FT_Pos   scaled;
 
 
     for ( n = 0; n < count; n++ )
@@ -1625,8 +1646,8 @@
   af_latin2_compute_stem_width( AF_GlyphHints  hints,
                                 AF_Dimension   dim,
                                 FT_Pos         width,
-                                AF_Edge_Flags  base_flags,
-                                AF_Edge_Flags  stem_flags )
+                                FT_UInt        base_flags,
+                                FT_UInt        stem_flags )
   {
     AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
     AF_LatinAxis     axis     = & metrics->axis[dim];
@@ -1797,10 +1818,9 @@
   {
     FT_Pos  dist = stem_edge->opos - base_edge->opos;
 
-    FT_Pos  fitted_width = af_latin2_compute_stem_width(
-                             hints, dim, dist,
-                             (AF_Edge_Flags)base_edge->flags,
-                             (AF_Edge_Flags)stem_edge->flags );
+    FT_Pos  fitted_width = af_latin2_compute_stem_width( hints, dim, dist,
+                                                         base_edge->flags,
+                                                         stem_edge->flags );
 
 
     stem_edge->pos = base_edge->pos + fitted_width;
@@ -1834,7 +1854,7 @@
   /*************************************************************************/
 
 
-  FT_LOCAL_DEF( void )
+  static void
   af_latin2_hint_edges( AF_GlyphHints  hints,
                         AF_Dimension   dim )
   {
@@ -1842,7 +1862,7 @@
     AF_Edge       edges      = axis->edges;
     AF_Edge       edge_limit = edges + axis->num_edges;
     AF_Edge       edge;
-    AF_Edge       anchor     = 0;
+    AF_Edge       anchor     = NULL;
     FT_Int        has_serifs = 0;
     FT_Pos        anchor_drift = 0;
 
@@ -1946,10 +1966,9 @@
 
 
         org_len = edge2->opos - edge->opos;
-        cur_len = af_latin2_compute_stem_width(
-                    hints, dim, org_len,
-                    (AF_Edge_Flags)edge->flags,
-                    (AF_Edge_Flags)edge2->flags );
+        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+                                                edge->flags,
+                                                edge2->flags );
         if ( cur_len <= 64 )
           u_off = d_off = 32;
         else
@@ -2011,10 +2030,9 @@
         org_len    = edge2->opos - edge->opos;
         org_center = org_pos + ( org_len >> 1 );
 
-        cur_len = af_latin2_compute_stem_width(
-                   hints, dim, org_len,
-                   (AF_Edge_Flags)edge->flags,
-                   (AF_Edge_Flags)edge2->flags );
+        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+                                                edge->flags,
+                                                edge2->flags );
 
         org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
         org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
@@ -2303,13 +2321,16 @@
 
 
   static FT_Error
-  af_latin2_hints_apply( AF_GlyphHints    hints,
+  af_latin2_hints_apply( FT_UInt          glyph_index,
+                         AF_GlyphHints    hints,
                          FT_Outline*      outline,
                          AF_LatinMetrics  metrics )
   {
     FT_Error  error;
     int       dim;
 
+    FT_UNUSED( glyph_index );
+
 
     error = af_glyph_hints_reload( hints, outline );
     if ( error )
@@ -2317,8 +2338,9 @@
 
     /* analyze glyph outline */
 #ifdef AF_CONFIG_OPTION_USE_WARPER
-    if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
-         AF_HINTS_DO_HORIZONTAL( hints ) )
+    if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+           AF_HINTS_DO_WARP( hints )                                ) ||
+         AF_HINTS_DO_HORIZONTAL( hints )                              )
 #else
     if ( AF_HINTS_DO_HORIZONTAL( hints ) )
 #endif
@@ -2341,8 +2363,9 @@
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
 #ifdef AF_CONFIG_OPTION_USE_WARPER
-      if ( ( dim == AF_DIMENSION_HORZ &&
-             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+      if ( dim == AF_DIMENSION_HORZ                                 &&
+           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+           AF_HINTS_DO_WARP( hints )                                )
       {
         AF_WarperRec  warper;
         FT_Fixed      scale;
@@ -2353,7 +2376,7 @@
         af_glyph_hints_scale_dim( hints, dim, scale, delta );
         continue;
       }
-#endif
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
 
       if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
            ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
@@ -2390,6 +2413,7 @@
     (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,
     (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,
     (AF_WritingSystem_DoneMetricsFunc) NULL,
+    (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths,
 
     (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,
     (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply
diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h
index b5d252a..f83f704 100644
--- a/src/autofit/aflatin2.h
+++ b/src/autofit/aflatin2.h
@@ -1,3 +1,8 @@
+/* ATTENTION: This file doesn't compile.  It is only here as a reference */
+/*            of an alternative latin hinting algorithm that was always  */
+/*            marked as experimental.                                    */
+
+
 /***************************************************************************/
 /*                                                                         */
 /*  aflatin2.h                                                             */
@@ -5,7 +10,7 @@
 /*    Auto-fitter hinting routines for latin writing system                */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2003-2007, 2012, 2013 by                                     */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +22,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFLATIN2_H__
-#define __AFLATIN2_H__
+#ifndef AFLATIN2_H_
+#define AFLATIN2_H_
 
 #include "afhints.h"
 
@@ -35,7 +40,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFLATIN_H__ */
+#endif /* AFLATIN_H_ */
 
 
 /* END */
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 0fa3c12..26bba06 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (body).                           */
 /*                                                                         */
-/*  Copyright 2003-2009, 2011-2014 by                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,41 +23,34 @@
 #include "afmodule.h"
 #include "afpic.h"
 
+#include FT_INTERNAL_CALC_H
+
 
   /* Initialize glyph loader. */
 
-  FT_LOCAL_DEF( FT_Error )
-  af_loader_init( AF_Module  module )
+  FT_LOCAL_DEF( void )
+  af_loader_init( AF_Loader      loader,
+                  AF_GlyphHints  hints )
   {
-    AF_Loader  loader = module->loader;
-    FT_Memory  memory = module->root.library->memory;
-
-
     FT_ZERO( loader );
 
-    af_glyph_hints_init( &loader->hints, memory );
-#ifdef FT_DEBUG_AUTOFIT
-    _af_debug_hints = &loader->hints;
-#endif
-    return FT_GlyphLoader_New( memory, &loader->gloader );
+    loader->hints = hints;
   }
 
 
   /* Reset glyph loader and compute globals if necessary. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_loader_reset( AF_Module  module,
+  af_loader_reset( AF_Loader  loader,
+                   AF_Module  module,
                    FT_Face    face )
   {
-    FT_Error   error  = FT_Err_Ok;
-    AF_Loader  loader = module->loader;
+    FT_Error  error = FT_Err_Ok;
 
 
     loader->face    = face;
     loader->globals = (AF_FaceGlobals)face->autohint.data;
 
-    FT_GlyphLoader_Rewind( loader->gloader );
-
     if ( loader->globals == NULL )
     {
       error = af_face_globals_new( face, &loader->globals, module );
@@ -77,42 +70,43 @@
   /* Finalize glyph loader. */
 
   FT_LOCAL_DEF( void )
-  af_loader_done( AF_Module  module )
+  af_loader_done( AF_Loader  loader )
   {
-    AF_Loader  loader = module->loader;
-
-
-    af_glyph_hints_done( &loader->hints );
-
     loader->face    = NULL;
     loader->globals = NULL;
-
-#ifdef FT_DEBUG_AUTOFIT
-    _af_debug_hints = NULL;
-#endif
-    FT_GlyphLoader_Done( loader->gloader );
-    loader->gloader = NULL;
+    loader->hints   = NULL;
   }
 
 
-  /* Load a single glyph component.  This routine calls itself */
-  /* recursively, if necessary, and does the main work of      */
-  /* `af_loader_load_glyph.'                                   */
+#define af_intToFixed( i ) \
+          ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define af_fixedToInt( x ) \
+          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define af_floatToFixed( f ) \
+          ( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
+
+
+  /* Do the main work of `af_loader_load_glyph'.  Note that we never   */
+  /* have to deal with composite glyphs as those get loaded into       */
+  /* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function. */
+  /* In the rare cases where FT_LOAD_NO_RECURSE is set, it implies     */
+  /* FT_LOAD_NO_SCALE and as such the auto-hinter is never called.     */
 
   static FT_Error
   af_loader_load_g( AF_Loader  loader,
                     AF_Scaler  scaler,
                     FT_UInt    glyph_index,
-                    FT_Int32   load_flags,
-                    FT_UInt    depth )
+                    FT_Int32   load_flags )
   {
+    AF_Module  module = loader->globals->module;
+
     FT_Error          error;
     FT_Face           face     = loader->face;
-    FT_GlyphLoader    gloader  = loader->gloader;
     AF_StyleMetrics   metrics  = loader->metrics;
-    AF_GlyphHints     hints    = &loader->hints;
+    AF_GlyphHints     hints    = loader->hints;
     FT_GlyphSlot      slot     = face->glyph;
     FT_Slot_Internal  internal = slot->internal;
+    FT_GlyphLoader    gloader  = internal->loader;
     FT_Int32          flags;
 
 
@@ -121,6 +115,132 @@
     if ( error )
       goto Exit;
 
+    /*
+     * Apply stem darkening (emboldening) here before hints are applied to
+     * the outline.  Glyphs are scaled down proportionally to the
+     * emboldening so that curve points don't fall outside their precomputed
+     * blue zones.
+     *
+     * Any emboldening done by the font driver (e.g., the CFF driver)
+     * doesn't reach here because the autohinter loads the unprocessed
+     * glyphs in font units for analysis (functions `af_*_metrics_init_*')
+     * and then above to prepare it for the rasterizers by itself,
+     * independently of the font driver.  So emboldening must be done here,
+     * within the autohinter.
+     *
+     * All glyphs to be autohinted pass through here one by one.  The
+     * standard widths can therefore change from one glyph to the next,
+     * depending on what script a glyph is assigned to (each script has its
+     * own set of standard widths and other metrics).  The darkening amount
+     * must therefore be recomputed for each size and
+     * `standard_{vertical,horizontal}_width' change.
+     */
+    if ( !module->no_stem_darkening )
+    {
+      AF_FaceGlobals         globals = loader->globals;
+      AF_WritingSystemClass  writing_system_class;
+
+      FT_Pos  stdVW = 0;
+      FT_Pos  stdHW = 0;
+
+      FT_Bool  size_changed = face->size->metrics.x_ppem
+                                != globals->stem_darkening_for_ppem;
+
+      FT_Fixed  em_size  = af_intToFixed( face->units_per_EM );
+      FT_Fixed  em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
+
+      FT_Matrix  scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
+
+
+      /* Skip stem darkening for broken fonts. */
+      if ( !face->units_per_EM )
+        goto After_Emboldening;
+
+      /*
+       * We depend on the writing system (script analyzers) to supply
+       * standard widths for the script of the glyph we are looking at.  If
+       * it can't deliver, stem darkening is effectively disabled.
+       */
+      writing_system_class =
+        AF_WRITING_SYSTEM_CLASSES_GET[metrics->style_class->writing_system];
+
+      if ( writing_system_class->style_metrics_getstdw )
+        writing_system_class->style_metrics_getstdw( metrics,
+                                                     &stdHW,
+                                                     &stdVW );
+      else
+        goto After_Emboldening;
+
+
+      if ( size_changed                                               ||
+           ( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
+      {
+        FT_Fixed  darken_by_font_units_x, darken_x;
+
+
+        darken_by_font_units_x =
+          af_intToFixed( af_loader_compute_darkening( loader,
+                                                      face,
+                                                      stdVW ) );
+        darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
+                                         face->size->metrics.x_scale ),
+                              em_ratio );
+
+        globals->standard_vertical_width = stdVW;
+        globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+        globals->darken_x                = af_fixedToInt( darken_x );
+      }
+
+      if ( size_changed                                                 ||
+           ( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
+      {
+        FT_Fixed  darken_by_font_units_y, darken_y;
+
+
+        darken_by_font_units_y =
+          af_intToFixed( af_loader_compute_darkening( loader,
+                                                      face,
+                                                      stdHW ) );
+        darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
+                                         face->size->metrics.y_scale ),
+                              em_ratio );
+
+        globals->standard_horizontal_width = stdHW;
+        globals->stem_darkening_for_ppem   = face->size->metrics.x_ppem;
+        globals->darken_y                  = af_fixedToInt( darken_y );
+
+        /*
+         * Scale outlines down on the Y-axis to keep them inside their blue
+         * zones.  The stronger the emboldening, the stronger the
+         * downscaling (plus heuristical padding to prevent outlines still
+         * falling out their zones due to rounding).
+         *
+         * Reason: `FT_Outline_Embolden' works by shifting the rightmost
+         * points of stems farther to the right, and topmost points farther
+         * up.  This positions points on the Y-axis outside their
+         * pre-computed blue zones and leads to distortion when applying the
+         * hints in the code further below.  Code outside this emboldening
+         * block doesn't know we are presenting it with modified outlines
+         * the analyzer didn't see!
+         *
+         * An unfortunate side effect of downscaling is that the emboldening
+         * effect is slightly decreased.  The loss becomes more pronounced
+         * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
+         */
+        globals->scale_down_factor =
+          FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
+                     em_size );
+      }
+
+      FT_Outline_EmboldenXY( &slot->outline,
+                             globals->darken_x,
+                             globals->darken_y );
+
+      scale_down_matrix.yy = globals->scale_down_factor;
+      FT_Outline_Transform( &slot->outline, &scale_down_matrix );
+    }
+
+  After_Emboldening:
     loader->transformed = internal->glyph_transformed;
     if ( loader->transformed )
     {
@@ -131,8 +251,8 @@
       loader->trans_delta  = internal->glyph_delta;
 
       inverse = loader->trans_matrix;
-      FT_Matrix_Invert( &inverse );
-      FT_Vector_Transform( &loader->trans_delta, &inverse );
+      if ( !FT_Matrix_Invert( &inverse ) )
+        FT_Vector_Transform( &loader->trans_delta, &inverse );
     }
 
     switch ( slot->format )
@@ -144,29 +264,6 @@
                               loader->trans_delta.x,
                               loader->trans_delta.y );
 
-      /* copy the outline points in the loader's current                */
-      /* extra points which are used to keep original glyph coordinates */
-      error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
-                                           slot->outline.n_points + 4,
-                                           slot->outline.n_contours );
-      if ( error )
-        goto Exit;
-
-      FT_ARRAY_COPY( gloader->current.outline.points,
-                     slot->outline.points,
-                     slot->outline.n_points );
-
-      FT_ARRAY_COPY( gloader->current.outline.contours,
-                     slot->outline.contours,
-                     slot->outline.n_contours );
-
-      FT_ARRAY_COPY( gloader->current.outline.tags,
-                     slot->outline.tags,
-                     slot->outline.n_points );
-
-      gloader->current.outline.n_points   = slot->outline.n_points;
-      gloader->current.outline.n_contours = slot->outline.n_contours;
-
       /* compute original horizontal phantom points (and ignore */
       /* vertical ones)                                         */
       loader->pp1.x = hints->x_delta;
@@ -191,8 +288,9 @@
 
 
         if ( writing_system_class->style_hints_apply )
-          writing_system_class->style_hints_apply( hints,
-                                                   &gloader->current.outline,
+          writing_system_class->style_hints_apply( glyph_index,
+                                                   hints,
+                                                   &gloader->base.outline,
                                                    metrics );
       }
 
@@ -267,128 +365,6 @@
         slot->rsb_delta = loader->pp2.x - pp2x;
       }
 
-      /* good, we simply add the glyph to our loader's base */
-      FT_GlyphLoader_Add( gloader );
-      break;
-
-    case FT_GLYPH_FORMAT_COMPOSITE:
-      {
-        FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
-        FT_UInt      num_base_subgs, start_point;
-        FT_SubGlyph  subglyph;
-
-
-        start_point = gloader->base.outline.n_points;
-
-        /* first of all, copy the subglyph descriptors in the glyph loader */
-        error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
-        if ( error )
-          goto Exit;
-
-        FT_ARRAY_COPY( gloader->current.subglyphs,
-                       slot->subglyphs,
-                       num_subglyphs );
-
-        gloader->current.num_subglyphs = num_subglyphs;
-        num_base_subgs                 = gloader->base.num_subglyphs;
-
-        /* now read each subglyph independently */
-        for ( nn = 0; nn < num_subglyphs; nn++ )
-        {
-          FT_Vector  pp1, pp2;
-          FT_Pos     x, y;
-          FT_UInt    num_points, num_new_points, num_base_points;
-
-
-          /* gloader.current.subglyphs can change during glyph loading due */
-          /* to re-allocation -- we must recompute the current subglyph on */
-          /* each iteration                                                */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          pp1 = loader->pp1;
-          pp2 = loader->pp2;
-
-          num_base_points = gloader->base.outline.n_points;
-
-          error = af_loader_load_g( loader, scaler, subglyph->index,
-                                    load_flags, depth + 1 );
-          if ( error )
-            goto Exit;
-
-          /* recompute subglyph pointer */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) )
-          {
-            loader->pp1 = pp1;
-            loader->pp2 = pp2;
-          }
-
-          num_points     = gloader->base.outline.n_points;
-          num_new_points = num_points - num_base_points;
-
-          /* now perform the transformation required for this subglyph */
-
-          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
-                                   FT_SUBGLYPH_FLAG_XY_SCALE |
-                                   FT_SUBGLYPH_FLAG_2X2      ) )
-          {
-            FT_Vector*  cur   = gloader->base.outline.points +
-                                num_base_points;
-            FT_Vector*  limit = cur + num_new_points;
-
-
-            for ( ; cur < limit; cur++ )
-              FT_Vector_Transform( cur, &subglyph->transform );
-          }
-
-          /* apply offset */
-
-          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
-          {
-            FT_Int      k = subglyph->arg1;
-            FT_UInt     l = subglyph->arg2;
-            FT_Vector*  p1;
-            FT_Vector*  p2;
-
-
-            if ( start_point + k >= num_base_points         ||
-                               l >= (FT_UInt)num_new_points )
-            {
-              error = FT_THROW( Invalid_Composite );
-              goto Exit;
-            }
-
-            l += num_base_points;
-
-            /* for now, only use the current point coordinates; */
-            /* we eventually may consider another approach      */
-            p1 = gloader->base.outline.points + start_point + k;
-            p2 = gloader->base.outline.points + start_point + l;
-
-            x = p1->x - p2->x;
-            y = p1->y - p2->y;
-          }
-          else
-          {
-            x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
-            y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
-
-            x = FT_PIX_ROUND( x );
-            y = FT_PIX_ROUND( y );
-          }
-
-          {
-            FT_Outline  dummy = gloader->base.outline;
-
-
-            dummy.points  += num_base_points;
-            dummy.n_points = (short)num_new_points;
-
-            FT_Outline_Translate( &dummy, x, y );
-          }
-        }
-      }
       break;
 
     default:
@@ -397,7 +373,6 @@
     }
 
   Hint_Metrics:
-    if ( depth == 0 )
     {
       FT_BBox    bbox;
       FT_Vector  vvector;
@@ -472,18 +447,14 @@
       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
       slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
 
-      /* now copy outline into glyph slot */
-      FT_GlyphLoader_Rewind( internal->loader );
-      error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
-      if ( error )
-        goto Exit;
-
+#if 0
       /* reassign all outline fields except flags to protect them */
       slot->outline.n_contours = internal->loader->base.outline.n_contours;
       slot->outline.n_points   = internal->loader->base.outline.n_points;
       slot->outline.points     = internal->loader->base.outline.points;
       slot->outline.tags       = internal->loader->base.outline.tags;
       slot->outline.contours   = internal->loader->base.outline.contours;
+#endif
 
       slot->format  = FT_GLYPH_FORMAT_OUTLINE;
     }
@@ -496,19 +467,19 @@
   /* Load a glyph. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_loader_load_glyph( AF_Module  module,
+  af_loader_load_glyph( AF_Loader  loader,
+                        AF_Module  module,
                         FT_Face    face,
                         FT_UInt    gindex,
                         FT_Int32   load_flags )
   {
     FT_Error      error;
     FT_Size       size   = face->size;
-    AF_Loader     loader = module->loader;
     AF_ScalerRec  scaler;
 
 
     if ( !size )
-      return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Size_Handle );
 
     FT_ZERO( &scaler );
 
@@ -521,7 +492,7 @@
     scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
     scaler.flags       = 0;  /* XXX: fix this */
 
-    error = af_loader_reset( module, face );
+    error = af_loader_reset( loader, module, face );
     if ( !error )
     {
       AF_StyleMetrics  metrics;
@@ -558,13 +529,13 @@
 
         if ( writing_system_class->style_hints_init )
         {
-          error = writing_system_class->style_hints_init( &loader->hints,
+          error = writing_system_class->style_hints_init( loader->hints,
                                                           metrics );
           if ( error )
             goto Exit;
         }
 
-        error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
+        error = af_loader_load_g( loader, &scaler, gindex, load_flags );
       }
     }
   Exit:
@@ -572,4 +543,134 @@
   }
 
 
+  /*
+   * Compute amount of font units the face should be emboldened by, in
+   * analogy to the CFF driver's `cf2_computeDarkening' function.  See there
+   * for details of the algorithm.
+   *
+   * XXX: Currently a crude adaption of the original algorithm.  Do better?
+   */
+  FT_LOCAL_DEF( FT_Int32 )
+  af_loader_compute_darkening( AF_Loader  loader,
+                               FT_Face    face,
+                               FT_Pos     standard_width )
+  {
+    AF_Module  module = loader->globals->module;
+
+    FT_UShort  units_per_EM;
+    FT_Fixed   ppem, em_ratio;
+    FT_Fixed   stem_width, stem_width_per_1000, scaled_stem, darken_amount;
+    FT_Int     log_base_2;
+    FT_Int     x1, y1, x2, y2, x3, y3, x4, y4;
+
+
+    ppem         = FT_MAX( af_intToFixed( 4 ),
+                           af_intToFixed( face->size->metrics.x_ppem ) );
+    units_per_EM = face->units_per_EM;
+
+    em_ratio = FT_DivFix( af_intToFixed( 1000 ),
+                          af_intToFixed ( units_per_EM ) );
+    if ( em_ratio < af_floatToFixed( .01 ) )
+    {
+      /* If something goes wrong, don't embolden. */
+      return 0;
+    }
+
+    x1 = module->darken_params[0];
+    y1 = module->darken_params[1];
+    x2 = module->darken_params[2];
+    y2 = module->darken_params[3];
+    x3 = module->darken_params[4];
+    y3 = module->darken_params[5];
+    x4 = module->darken_params[6];
+    y4 = module->darken_params[7];
+
+    if ( standard_width <= 0 )
+    {
+      stem_width          = af_intToFixed( 75 ); /* taken from cf2font.c */
+      stem_width_per_1000 = stem_width;
+    }
+    else
+    {
+      stem_width          = af_intToFixed( standard_width );
+      stem_width_per_1000 = FT_MulFix( stem_width, em_ratio );
+    }
+
+    log_base_2 = FT_MSB( (FT_UInt32)stem_width_per_1000 ) +
+                 FT_MSB( (FT_UInt32)ppem );
+
+    if ( log_base_2 >= 46 )
+    {
+      /* possible overflow */
+      scaled_stem = af_intToFixed( x4 );
+    }
+    else
+      scaled_stem = FT_MulFix( stem_width_per_1000, ppem );
+
+    /* now apply the darkening parameters */
+    if ( scaled_stem < af_intToFixed( x1 ) )
+      darken_amount = FT_DivFix( af_intToFixed( y1 ), ppem );
+
+    else if ( scaled_stem < af_intToFixed( x2 ) )
+    {
+      FT_Int  xdelta = x2 - x1;
+      FT_Int  ydelta = y2 - y1;
+      FT_Int  x      = stem_width_per_1000 -
+                       FT_DivFix( af_intToFixed( x1 ), ppem );
+
+
+      if ( !xdelta )
+        goto Try_x3;
+
+      darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+                      FT_DivFix( af_intToFixed( y1 ), ppem );
+    }
+
+    else if ( scaled_stem < af_intToFixed( x3 ) )
+    {
+    Try_x3:
+      {
+        FT_Int  xdelta = x3 - x2;
+        FT_Int  ydelta = y3 - y2;
+        FT_Int  x      = stem_width_per_1000 -
+                         FT_DivFix( af_intToFixed( x2 ), ppem );
+
+
+        if ( !xdelta )
+          goto Try_x4;
+
+        darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+                        FT_DivFix( af_intToFixed( y2 ), ppem );
+      }
+    }
+
+    else if ( scaled_stem < af_intToFixed( x4 ) )
+    {
+    Try_x4:
+      {
+        FT_Int  xdelta = x4 - x3;
+        FT_Int  ydelta = y4 - y3;
+        FT_Int  x      = stem_width_per_1000 -
+                         FT_DivFix( af_intToFixed( x3 ), ppem );
+
+
+        if ( !xdelta )
+          goto Use_y4;
+
+        darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+                        FT_DivFix( af_intToFixed( y3 ), ppem );
+      }
+    }
+
+    else
+    {
+    Use_y4:
+      darken_amount = FT_DivFix( af_intToFixed( y4 ), ppem );
+    }
+
+    /* Convert darken_amount from per 1000 em to true character space. */
+    return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
+  }
+
+
 /* END */
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index 9601e24..0062eb9 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (specification).                  */
 /*                                                                         */
-/*  Copyright 2003-2005, 2011-2013 by                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,17 +16,16 @@
 /***************************************************************************/
 
 
-#ifndef __AFLOADER_H__
-#define __AFLOADER_H__
+#ifndef AFLOADER_H_
+#define AFLOADER_H_
 
 #include "afhints.h"
+#include "afmodule.h"
 #include "afglobal.h"
 
 
 FT_BEGIN_HEADER
 
-  typedef struct AF_ModuleRec_*  AF_Module;
-
   /*
    *  The autofitter module's (global) data structure to communicate with
    *  actual fonts.  If necessary, `local' data like the current face, the
@@ -42,8 +41,7 @@
     AF_FaceGlobals    globals;
 
     /* current glyph data */
-    FT_GlyphLoader    gloader;
-    AF_GlyphHintsRec  hints;
+    AF_GlyphHints     hints;
     AF_StyleMetrics   metrics;
     FT_Bool           transformed;
     FT_Matrix         trans_matrix;
@@ -55,31 +53,39 @@
   } AF_LoaderRec, *AF_Loader;
 
 
-  FT_LOCAL( FT_Error )
-  af_loader_init( AF_Module  module );
+  FT_LOCAL( void )
+  af_loader_init( AF_Loader      loader,
+                  AF_GlyphHints  hints );
 
 
   FT_LOCAL( FT_Error )
-  af_loader_reset( AF_Module  module,
+  af_loader_reset( AF_Loader  loader,
+                   AF_Module  module,
                    FT_Face    face );
 
 
   FT_LOCAL( void )
-  af_loader_done( AF_Module  module );
+  af_loader_done( AF_Loader  loader );
 
 
   FT_LOCAL( FT_Error )
-  af_loader_load_glyph( AF_Module  module,
+  af_loader_load_glyph( AF_Loader  loader,
+                        AF_Module  module,
                         FT_Face    face,
                         FT_UInt    gindex,
                         FT_Int32   load_flags );
 
+  FT_LOCAL_DEF( FT_Int32 )
+  af_loader_compute_darkening( AF_Loader  loader,
+                               FT_Face    face,
+                               FT_Pos     standard_width );
+
 /* */
 
 
 FT_END_HEADER
 
-#endif /* __AFLOADER_H__ */
+#endif /* AFLOADER_H_ */
 
 
 /* END */
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index 181cf55..e8f8ff4 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (body).                            */
 /*                                                                         */
-/*  Copyright 2003-2006, 2009, 2011-2014 by                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,10 +23,35 @@
 #include "afpic.h"
 
 #ifdef FT_DEBUG_AUTOFIT
-  int    _af_debug_disable_horz_hints;
-  int    _af_debug_disable_vert_hints;
-  int    _af_debug_disable_blue_hints;
-  void*  _af_debug_hints;
+
+#ifndef FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+  extern void
+  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
+                                FT_Bool        to_stdout );
+  extern void
+  af_glyph_hints_dump_points( AF_GlyphHints  hints,
+                              FT_Bool        to_stdout );
+  extern void
+  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
+                             FT_Bool        to_stdout );
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
+
+  int  _af_debug_disable_horz_hints;
+  int  _af_debug_disable_vert_hints;
+  int  _af_debug_disable_blue_hints;
+
+  /* we use a global object instead of a local one for debugging */
+  AF_GlyphHintsRec  _af_debug_hints_rec[1];
+
+  void*  _af_debug_hints = _af_debug_hints_rec;
 #endif
 
 #include FT_INTERNAL_OBJECTS_H
@@ -55,7 +80,7 @@
 
 
     if ( !face )
-      return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Face_Handle );
 
     globals = (AF_FaceGlobals)face->autohint.data;
     if ( !globals )
@@ -82,18 +107,29 @@
   static FT_Error
   af_property_set( FT_Module    ft_module,
                    const char*  property_name,
-                   const void*  value )
+                   const void*  value,
+                   FT_Bool      value_is_string )
   {
     FT_Error   error  = FT_Err_Ok;
     AF_Module  module = (AF_Module)ft_module;
 
+#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+    FT_UNUSED( value_is_string );
+#endif
+
 
     if ( !ft_strcmp( property_name, "fallback-script" ) )
     {
-      FT_UInt*  fallback_script = (FT_UInt*)value;
+      FT_UInt*  fallback_script;
+      FT_UInt   ss;
 
-      FT_UInt  ss;
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+        return FT_THROW( Invalid_Argument );
+#endif
+
+      fallback_script = (FT_UInt*)value;
 
       /* We translate the fallback script to a fallback style that uses */
       /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its  */
@@ -122,25 +158,157 @@
     }
     else if ( !ft_strcmp( property_name, "default-script" ) )
     {
-      FT_UInt*  default_script = (FT_UInt*)value;
+      FT_UInt*  default_script;
 
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+        return FT_THROW( Invalid_Argument );
+#endif
+
+      default_script = (FT_UInt*)value;
+
       module->default_script = *default_script;
 
       return error;
     }
     else if ( !ft_strcmp( property_name, "increase-x-height" ) )
     {
-      FT_Prop_IncreaseXHeight*  prop = (FT_Prop_IncreaseXHeight*)value;
+      FT_Prop_IncreaseXHeight*  prop;
       AF_FaceGlobals            globals;
 
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+        return FT_THROW( Invalid_Argument );
+#endif
+
+      prop = (FT_Prop_IncreaseXHeight*)value;
+
       error = af_property_get_face_globals( prop->face, &globals, module );
       if ( !error )
         globals->increase_x_height = prop->limit;
 
       return error;
     }
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    else if ( !ft_strcmp( property_name, "warping" ) )
+    {
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
+        long         w = ft_strtol( s, NULL, 10 );
+
+
+        if ( w == 0 )
+          module->warping = 0;
+        else if ( w == 1 )
+          module->warping = 1;
+        else
+          return FT_THROW( Invalid_Argument );
+      }
+      else
+#endif
+      {
+        FT_Bool*  warping = (FT_Bool*)value;
+
+
+        module->warping = *warping;
+      }
+
+      return error;
+    }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params;
+      FT_Int   x1, y1, x2, y2, x3, y3, x4, y4;
+
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      FT_Int   dp[8];
+
+
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
+        char*        ep;
+        int          i;
+
+
+        /* eight comma-separated numbers */
+        for ( i = 0; i < 7; i++ )
+        {
+          dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
+          if ( *ep != ',' || s == ep )
+            return FT_THROW( Invalid_Argument );
+
+          s = ep + 1;
+        }
+
+        dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
+        if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
+          return FT_THROW( Invalid_Argument );
+
+        darken_params = dp;
+      }
+      else
+#endif
+        darken_params = (FT_Int*)value;
+
+      x1 = darken_params[0];
+      y1 = darken_params[1];
+      x2 = darken_params[2];
+      y2 = darken_params[3];
+      x3 = darken_params[4];
+      y3 = darken_params[5];
+      x4 = darken_params[6];
+      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 );
+
+      module->darken_params[0] = x1;
+      module->darken_params[1] = y1;
+      module->darken_params[2] = x2;
+      module->darken_params[3] = y2;
+      module->darken_params[4] = x3;
+      module->darken_params[5] = y3;
+      module->darken_params[6] = x4;
+      module->darken_params[7] = y4;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+    {
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s   = (const char*)value;
+        long         nsd = ft_strtol( s, NULL, 10 );
+
+
+        if ( nsd == 0 )
+          module->no_stem_darkening = 0;
+        else if ( nsd == 1 )
+          module->no_stem_darkening = 1;
+        else
+          return FT_THROW( Invalid_Argument );
+      }
+      else
+#endif
+      {
+        FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+
+
+        module->no_stem_darkening = *no_stem_darkening;
+      }
+
+      return error;
+    }
 
     FT_TRACE0(( "af_property_set: missing property `%s'\n",
                 property_name ));
@@ -157,6 +325,9 @@
     AF_Module  module         = (AF_Module)ft_module;
     FT_UInt    fallback_style = module->fallback_style;
     FT_UInt    default_script = module->default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    FT_Bool    warping        = module->warping;
+#endif
 
 
     if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
@@ -203,8 +374,45 @@
 
       return error;
     }
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    else if ( !ft_strcmp( property_name, "warping" ) )
+    {
+      FT_Bool*  val = (FT_Bool*)value;
 
 
+      *val = warping;
+
+      return error;
+    }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = module->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, "no-stem-darkening" ) )
+    {
+      FT_Bool   no_stem_darkening = module->no_stem_darkening;
+      FT_Bool*  val               = (FT_Bool*)value;
+
+
+      *val = no_stem_darkening;
+
+      return error;
+    }
+
     FT_TRACE0(( "af_property_get: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
@@ -213,8 +421,8 @@
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     af_service_properties,
-    (FT_Properties_SetFunc)af_property_set,
-    (FT_Properties_GetFunc)af_property_get )
+    (FT_Properties_SetFunc)af_property_set,        /* set_property */
+    (FT_Properties_GetFunc)af_property_get )       /* get_property */
 
 
   FT_DEFINE_SERVICEDESCREC1(
@@ -226,7 +434,7 @@
   af_get_interface( FT_Module    module,
                     const char*  module_interface )
   {
-    /* AF_SERVICES_GET derefers `library' in PIC mode */
+    /* AF_SERVICES_GET dereferences `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     FT_Library  library;
 
@@ -250,20 +458,35 @@
     AF_Module  module = (AF_Module)ft_module;
 
 
-    module->fallback_style = AF_STYLE_FALLBACK;
-    module->default_script = AF_SCRIPT_DEFAULT;
+    module->fallback_style    = AF_STYLE_FALLBACK;
+    module->default_script    = AF_SCRIPT_DEFAULT;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    module->warping           = 0;
+#endif
+    module->no_stem_darkening = TRUE;
 
-    return af_loader_init( module );
+    module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+    module->darken_params[1]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+    module->darken_params[2]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+    module->darken_params[3]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+    module->darken_params[4]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+    module->darken_params[5]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+    module->darken_params[6]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+    module->darken_params[7]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
+
+    return FT_Err_Ok;
   }
 
 
   FT_CALLBACK_DEF( void )
   af_autofitter_done( FT_Module  ft_module )      /* AF_Module */
   {
-    AF_Module  module = (AF_Module)ft_module;
+    FT_UNUSED( ft_module );
 
-
-    af_loader_done( module );
+#ifdef FT_DEBUG_AUTOFIT
+    if ( _af_debug_hints_rec->memory )
+      af_glyph_hints_done( _af_debug_hints_rec );
+#endif
   }
 
 
@@ -274,10 +497,56 @@
                             FT_UInt       glyph_index,
                             FT_Int32      load_flags )
   {
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = module->root.library->memory;
+
+#ifdef FT_DEBUG_AUTOFIT
+
+    /* in debug mode, we use a global object that survives this routine */
+
+    AF_GlyphHints  hints = _af_debug_hints_rec;
+    AF_LoaderRec   loader[1];
+
     FT_UNUSED( size );
 
-    return af_loader_load_glyph( module, slot->face,
-                                 glyph_index, load_flags );
+
+    if ( hints->memory )
+      af_glyph_hints_done( hints );
+
+    af_glyph_hints_init( hints, memory );
+    af_loader_init( loader, hints );
+
+    error = af_loader_load_glyph( loader, module, slot->face,
+                                  glyph_index, load_flags );
+
+    af_glyph_hints_dump_points( hints, 0 );
+    af_glyph_hints_dump_segments( hints, 0 );
+    af_glyph_hints_dump_edges( hints, 0 );
+
+    af_loader_done( loader );
+
+    return error;
+
+#else /* !FT_DEBUG_AUTOFIT */
+
+    AF_GlyphHintsRec  hints[1];
+    AF_LoaderRec      loader[1];
+
+    FT_UNUSED( size );
+
+
+    af_glyph_hints_init( hints, memory );
+    af_loader_init( loader, hints );
+
+    error = af_loader_load_glyph( loader, module, slot->face,
+                                  glyph_index, load_flags );
+
+    af_loader_done( loader );
+    af_glyph_hints_done( hints );
+
+    return error;
+
+#endif /* !FT_DEBUG_AUTOFIT */
   }
 
 
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index 20b7b9f..e65db5f 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (specification).                   */
 /*                                                                         */
-/*  Copyright 2003-2005, 2009, 2012, 2013 by                               */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,24 +16,20 @@
 /***************************************************************************/
 
 
-#ifndef __AFMODULE_H__
-#define __AFMODULE_H__
+#ifndef AFMODULE_H_
+#define AFMODULE_H_
 
 #include <ft2build.h>
 #include FT_INTERNAL_OBJECTS_H
 #include FT_MODULE_H
 
-#include "afloader.h"
-
 
 FT_BEGIN_HEADER
 
 
   /*
-   *  This is the `extended' FT_Module structure which holds the
-   *  autofitter's global data.  Right before hinting a glyph, the data
-   *  specific to the glyph's face (blue zones, stem widths, etc.) are
-   *  loaded into `loader' (see function `af_loader_reset').
+   *  This is the `extended' FT_Module structure that holds the
+   *  autofitter's global data.
    */
 
   typedef struct  AF_ModuleRec_
@@ -42,18 +38,21 @@
 
     FT_UInt       fallback_style;
     FT_UInt       default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+    FT_Bool       warping;
+#endif
+    FT_Bool       no_stem_darkening;
+    FT_Int        darken_params[8];
 
-    AF_LoaderRec  loader[1];
-
-  } AF_ModuleRec;
+  } AF_ModuleRec, *AF_Module;
 
 
-FT_DECLARE_MODULE(autofit_module_class)
+FT_DECLARE_MODULE( autofit_module_class )
 
 
 FT_END_HEADER
 
-#endif /* __AFMODULE_H__ */
+#endif /* AFMODULE_H_ */
 
 
 /* END */
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index cb29fd7..3cbd916 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for autofit module.  */
 /*                                                                         */
-/*  Copyright 2009-2014 by                                                 */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -122,7 +122,7 @@
 #include "afwrtsys.h"
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 )          \
+#define SCRIPT( s, S, d, h, H, sss )                 \
         FT_Init_Class_af_ ## s ## _script_class(     \
           &container->af_script_classes_rec[ss++] );
 
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 9a68b4a..98a45a2 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-2013 by                                           */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,12 +16,10 @@
 /***************************************************************************/
 
 
-#ifndef __AFPIC_H__
-#define __AFPIC_H__
+#ifndef AFPIC_H_
+#define AFPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
 
@@ -43,6 +41,8 @@
 #include "aftypes.h"
 
 
+FT_BEGIN_HEADER
+
   typedef struct  AFModulePIC_
   {
     FT_ServiceDescRec*          af_services;
@@ -93,13 +93,13 @@
   FT_Error
   autofit_module_class_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
-FT_END_HEADER
-
-#endif /* __AFPIC_H__ */
+#endif /* AFPIC_H_ */
 
 
 /* END */
diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c
index 139a4c1..732f3d1 100644
--- a/src/autofit/afranges.c
+++ b/src/autofit/afranges.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter Unicode script ranges (body).                            */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,148 +18,647 @@
 
 #include "afranges.h"
 
+  /*
+   * The algorithm for assigning properties and styles to the `glyph_styles'
+   * array is as follows (cf. the implementation in
+   * `af_face_globals_compute_style_coverage').
+   *
+   *   Walk over all scripts (as listed in `afscript.h').
+   *
+   *   For a given script, walk over all styles (as listed in `afstyles.h').
+   *   The order of styles is important and should be as follows.
+   *
+   *   - First come styles based on OpenType features (small caps, for
+   *     example).  Since features rely on glyph indices, thus completely
+   *     bypassing character codes, no properties are assigned.
+   *
+   *   - Next comes the default style, using the character ranges as defined
+   *     below.  This also assigns properties.
+   *
+   *   Note that there also exist fallback scripts, mainly covering
+   *   superscript and subscript glyphs of a script that are not present as
+   *   OpenType features.  Fallback scripts are defined below, also
+   *   assigning properties; they are applied after the corresponding
+   *   script.
+   *
+   */
 
-  const AF_Script_UniRangeRec  af_cyrl_uniranges[] =
+
+  /* XXX Check base character ranges again:                        */
+  /*     Right now, they are quickly derived by visual inspection. */
+  /*     I can imagine that fine-tuning is necessary.              */
+
+  /* for the auto-hinter, a `non-base character' is something that should */
+  /* not be affected by blue zones, regardless of whether this is a       */
+  /* spacing or no-spacing glyph                                          */
+
+  /* the `ta_xxxx_nonbase_uniranges' ranges must be strict subsets */
+  /* of the corresponding `ta_xxxx_uniranges' ranges               */
+
+
+  const AF_Script_UniRangeRec  af_arab_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 )
+    AF_UNIRANGE_REC(  0x0600,  0x06FF ),  /* Arabic                                 */
+    AF_UNIRANGE_REC(  0x0750,  0x07FF ),  /* Arabic Supplement                      */
+    AF_UNIRANGE_REC(  0x08A0,  0x08FF ),  /* Arabic Extended-A                      */
+    AF_UNIRANGE_REC(  0xFB50,  0xFDFF ),  /* Arabic Presentation Forms-A            */
+    AF_UNIRANGE_REC(  0xFE70,  0xFEFF ),  /* Arabic Presentation Forms-B            */
+    AF_UNIRANGE_REC( 0x1EE00, 0x1EEFF ),  /* Arabic Mathematical Alphabetic Symbols */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_deva_uniranges[] =
+  const AF_Script_UniRangeRec  af_arab_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0900UL,  0x097FUL ),  /* Devanagari       */
-    AF_UNIRANGE_REC(  0x20B9UL,  0x20B9UL ),  /* (new) Rupee sign */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0600,  0x0605 ),
+    AF_UNIRANGE_REC(  0x0610,  0x061A ),
+    AF_UNIRANGE_REC(  0x064B,  0x065F ),
+    AF_UNIRANGE_REC(  0x0670,  0x0670 ),
+    AF_UNIRANGE_REC(  0x06D6,  0x06DC ),
+    AF_UNIRANGE_REC(  0x06DF,  0x06E4 ),
+    AF_UNIRANGE_REC(  0x06E7,  0x06E8 ),
+    AF_UNIRANGE_REC(  0x06EA,  0x06ED ),
+    AF_UNIRANGE_REC(  0x08D4,  0x08E1 ),
+    AF_UNIRANGE_REC(  0x08E3,  0x08FF ),
+    AF_UNIRANGE_REC(  0xFBB2,  0xFBC1 ),
+    AF_UNIRANGE_REC(  0xFE70,  0xFE70 ),
+    AF_UNIRANGE_REC(  0xFE72,  0xFE72 ),
+    AF_UNIRANGE_REC(  0xFE74,  0xFE74 ),
+    AF_UNIRANGE_REC(  0xFE76,  0xFE76 ),
+    AF_UNIRANGE_REC(  0xFE78,  0xFE78 ),
+    AF_UNIRANGE_REC(  0xFE7A,  0xFE7A ),
+    AF_UNIRANGE_REC(  0xFE7C,  0xFE7C ),
+    AF_UNIRANGE_REC(  0xFE7E,  0xFE7E ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_grek_uniranges[] =
+
+  const AF_Script_UniRangeRec  af_armn_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
-    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended   */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0530,  0x058F ),  /* Armenian                          */
+    AF_UNIRANGE_REC(  0xFB13,  0xFB17 ),  /* Alphab. Present. Forms (Armenian) */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_hebr_uniranges[] =
+  const AF_Script_UniRangeRec  af_armn_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0590UL,  0x05FFUL ),  /* Hebrew                          */
-    AF_UNIRANGE_REC(  0xFB1DUL,  0xFB4FUL ),  /* Alphab. Present. Forms (Hebrew) */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0559,  0x055F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  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,  0x20B8UL ),  /* Currency Symbols ...                   */
-    AF_UNIRANGE_REC(  0x20BAUL,  0x20CFUL ),  /* ... except new Rupee sign              */
-    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 )
-  };
-
-  const AF_Script_UniRangeRec  af_none_uniranges[] =
-  {
-    AF_UNIRANGE_REC( 0UL, 0UL )
-  };
-
-#ifdef AF_CONFIG_OPTION_INDIC
 
   const AF_Script_UniRangeRec  af_beng_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0980UL,  0x09FFUL ),  /* Bengali */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0980,  0x09FF ),  /* Bengali */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+  const AF_Script_UniRangeRec  af_beng_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0981,  0x0981 ),
+    AF_UNIRANGE_REC(  0x09BC,  0x09BC ),
+    AF_UNIRANGE_REC(  0x09C1,  0x09C4 ),
+    AF_UNIRANGE_REC(  0x09CD,  0x09CD ),
+    AF_UNIRANGE_REC(  0x09E2,  0x09E3 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_cher_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x13A0,  0x13FF ),  /* Cherokee            */
+    AF_UNIRANGE_REC(  0xAB70,  0xABBF ),  /* Cherokee Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_cher_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_cyrl_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0400,  0x04FF ),  /* Cyrillic            */
+    AF_UNIRANGE_REC(  0x0500,  0x052F ),  /* Cyrillic Supplement */
+    AF_UNIRANGE_REC(  0x2DE0,  0x2DFF ),  /* Cyrillic Extended-A */
+    AF_UNIRANGE_REC(  0xA640,  0xA69F ),  /* Cyrillic Extended-B */
+    AF_UNIRANGE_REC(  0x1C80,  0x1C8F ),  /* Cyrillic Extended-C */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_cyrl_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0483,  0x0489 ),
+    AF_UNIRANGE_REC(  0x2DE0,  0x2DFF ),
+    AF_UNIRANGE_REC(  0xA66F,  0xA67F ),
+    AF_UNIRANGE_REC(  0xA69E,  0xA69F ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  /* There are some characters in the Devanagari Unicode block that are    */
+  /* generic to Indic scripts; we omit them so that their presence doesn't */
+  /* trigger Devanagari.                                                   */
+
+  const AF_Script_UniRangeRec  af_deva_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0900,  0x093B ),  /* Devanagari          */
+    /* omitting U+093C nukta */
+    AF_UNIRANGE_REC(  0x093D,  0x0950 ),  /* ... continued       */
+    /* omitting U+0951 udatta, U+0952 anudatta */
+    AF_UNIRANGE_REC(  0x0953,  0x0963 ),  /* ... continued       */
+    /* omitting U+0964 danda, U+0965 double danda */
+    AF_UNIRANGE_REC(  0x0966,  0x097F ),  /* ... continued       */
+    AF_UNIRANGE_REC(  0x20B9,  0x20B9 ),  /* (new) Rupee sign    */
+    AF_UNIRANGE_REC(  0xA8E0,  0xA8FF ),  /* Devanagari Extended */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_deva_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0900,  0x0902 ),
+    AF_UNIRANGE_REC(  0x093A,  0x093A ),
+    AF_UNIRANGE_REC(  0x0941,  0x0948 ),
+    AF_UNIRANGE_REC(  0x094D,  0x094D ),
+    AF_UNIRANGE_REC(  0x0953,  0x0957 ),
+    AF_UNIRANGE_REC(  0x0962,  0x0963 ),
+    AF_UNIRANGE_REC(  0xA8E0,  0xA8F1 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_ethi_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1200,  0x137F ),  /* Ethiopic            */
+    AF_UNIRANGE_REC(  0x1380,  0x139F ),  /* Ethiopic Supplement */
+    AF_UNIRANGE_REC(  0x2D80,  0x2DDF ),  /* Ethiopic Extended   */
+    AF_UNIRANGE_REC(  0xAB00,  0xAB2F ),  /* Ethiopic Extended-A */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_ethi_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x135D,  0x135F ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_geor_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x10D0,  0x10FF ),  /* Georgian (Mkhedruli) */
+#if 0
+    /* the following range is proposed for inclusion in Unicode */
+    AF_UNIRANGE_REC(  0x1C90,  0x1CBF ),  /* Georgian (Mtavruli)  */
+#endif
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_geor_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_geok_uniranges[] =
+  {
+    /* Khutsuri */
+    AF_UNIRANGE_REC(  0x10A0,  0x10CD ),  /* Georgian (Asomtavruli) */
+    AF_UNIRANGE_REC(  0x2D00,  0x2D2D ),  /* Georgian (Nuskhuri)    */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_geok_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_grek_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0370,  0x03FF ),  /* Greek and Coptic */
+    AF_UNIRANGE_REC(  0x1F00,  0x1FFF ),  /* Greek Extended   */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_grek_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x037A,  0x037A ),
+    AF_UNIRANGE_REC(  0x0384,  0x0385 ),
+    AF_UNIRANGE_REC(  0x1FBD,  0x1FC1 ),
+    AF_UNIRANGE_REC(  0x1FCD,  0x1FCF ),
+    AF_UNIRANGE_REC(  0x1FDD,  0x1FDF ),
+    AF_UNIRANGE_REC(  0x1FED,  0x1FEF ),
+    AF_UNIRANGE_REC(  0x1FFD,  0x1FFE ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_gujr_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A80UL,  0x0AFFUL ),  /* Gujarati */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0A80,  0x0AFF ),  /* Gujarati */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+  const AF_Script_UniRangeRec  af_gujr_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A81,  0x0A82 ),
+    AF_UNIRANGE_REC(  0x0ABC,  0x0ABC ),
+    AF_UNIRANGE_REC(  0x0AC1,  0x0AC8 ),
+    AF_UNIRANGE_REC(  0x0ACD,  0x0ACD ),
+    AF_UNIRANGE_REC(  0x0AE2,  0x0AE3 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_guru_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A00UL,  0x0A7FUL ),  /* Gurmukhi */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0A00,  0x0A7F ),  /* Gurmukhi */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+  const AF_Script_UniRangeRec  af_guru_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A01,  0x0A02 ),
+    AF_UNIRANGE_REC(  0x0A3C,  0x0A3C ),
+    AF_UNIRANGE_REC(  0x0A41,  0x0A51 ),
+    AF_UNIRANGE_REC(  0x0A70,  0x0A71 ),
+    AF_UNIRANGE_REC(  0x0A75,  0x0A75 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_hebr_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0590,  0x05FF ),  /* Hebrew                          */
+    AF_UNIRANGE_REC(  0xFB1D,  0xFB4F ),  /* Alphab. Present. Forms (Hebrew) */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_hebr_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0591,  0x05BF ),
+    AF_UNIRANGE_REC(  0x05C1,  0x05C2 ),
+    AF_UNIRANGE_REC(  0x05C4,  0x05C5 ),
+    AF_UNIRANGE_REC(  0x05C7,  0x05C7 ),
+    AF_UNIRANGE_REC(  0xFB1E,  0xFB1E ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_knda_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C80UL,  0x0CFFUL ),  /* Kannada */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C80,  0x0CFF ),  /* Kannada */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_limb_uniranges[] =
+  const AF_Script_UniRangeRec  af_knda_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1900UL,  0x194FUL ),  /* Limbu */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C81,  0x0C81 ),
+    AF_UNIRANGE_REC(  0x0CBC,  0x0CBC ),
+    AF_UNIRANGE_REC(  0x0CBF,  0x0CBF ),
+    AF_UNIRANGE_REC(  0x0CC6,  0x0CC6 ),
+    AF_UNIRANGE_REC(  0x0CCC,  0x0CCD ),
+    AF_UNIRANGE_REC(  0x0CE2,  0x0CE3 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+
+  const AF_Script_UniRangeRec  af_khmr_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1780,  0x17FF ),  /* Khmer */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_khmr_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x17B7,  0x17BD ),
+    AF_UNIRANGE_REC(  0x17C6,  0x17C6 ),
+    AF_UNIRANGE_REC(  0x17C9,  0x17D3 ),
+    AF_UNIRANGE_REC(  0x17DD,  0x17DD ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_khms_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x19E0,  0x19FF ),  /* Khmer Symbols */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_khms_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_lao_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0E80,  0x0EFF ),  /* Lao */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_lao_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0EB1,  0x0EB1 ),
+    AF_UNIRANGE_REC(  0x0EB4,  0x0EBC ),
+    AF_UNIRANGE_REC(  0x0EC8,  0x0ECD ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_latn_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0020,  0x007F ),  /* Basic Latin (no control chars)         */
+    AF_UNIRANGE_REC(  0x00A0,  0x00A9 ),  /* Latin-1 Supplement (no control chars)  */
+    AF_UNIRANGE_REC(  0x00AB,  0x00B1 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x00B4,  0x00B8 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x00BB,  0x00FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x0100,  0x017F ),  /* Latin Extended-A                       */
+    AF_UNIRANGE_REC(  0x0180,  0x024F ),  /* Latin Extended-B                       */
+    AF_UNIRANGE_REC(  0x0250,  0x02AF ),  /* IPA Extensions                         */
+    AF_UNIRANGE_REC(  0x02B9,  0x02DF ),  /* Spacing Modifier Letters               */
+    AF_UNIRANGE_REC(  0x02E5,  0x02FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x0300,  0x036F ),  /* Combining Diacritical Marks            */
+    AF_UNIRANGE_REC(  0x1AB0,  0x1ABE ),  /* Combining Diacritical Marks Extended   */
+    AF_UNIRANGE_REC(  0x1D00,  0x1D2B ),  /* Phonetic Extensions                    */
+    AF_UNIRANGE_REC(  0x1D6B,  0x1D77 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x1D79,  0x1D7F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x1D80,  0x1D9A ),  /* Phonetic Extensions Supplement         */
+    AF_UNIRANGE_REC(  0x1DC0,  0x1DFF ),  /* Combining Diacritical Marks Supplement */
+    AF_UNIRANGE_REC(  0x1E00,  0x1EFF ),  /* Latin Extended Additional              */
+    AF_UNIRANGE_REC(  0x2000,  0x206F ),  /* General Punctuation                    */
+    AF_UNIRANGE_REC(  0x20A0,  0x20B8 ),  /* Currency Symbols ...                   */
+    AF_UNIRANGE_REC(  0x20BA,  0x20CF ),  /* ... except new Rupee sign              */
+    AF_UNIRANGE_REC(  0x2150,  0x218F ),  /* Number Forms                           */
+    AF_UNIRANGE_REC(  0x2C60,  0x2C7B ),  /* Latin Extended-C                       */
+    AF_UNIRANGE_REC(  0x2C7E,  0x2C7F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x2E00,  0x2E7F ),  /* Supplemental Punctuation               */
+    AF_UNIRANGE_REC(  0xA720,  0xA76F ),  /* Latin Extended-D                       */
+    AF_UNIRANGE_REC(  0xA771,  0xA7F7 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xA7FA,  0xA7FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xAB30,  0xAB5B ),  /* Latin Extended-E                       */
+    AF_UNIRANGE_REC(  0xAB60,  0xAB6F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xFB00,  0xFB06 ),  /* Alphab. Present. Forms (Latin Ligs)    */
+    AF_UNIRANGE_REC( 0x1D400, 0x1D7FF ),  /* Mathematical Alphanumeric Symbols      */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_latn_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x005E,  0x0060 ),
+    AF_UNIRANGE_REC(  0x007E,  0x007E ),
+    AF_UNIRANGE_REC(  0x00A8,  0x00A9 ),
+    AF_UNIRANGE_REC(  0x00AE,  0x00B0 ),
+    AF_UNIRANGE_REC(  0x00B4,  0x00B4 ),
+    AF_UNIRANGE_REC(  0x00B8,  0x00B8 ),
+    AF_UNIRANGE_REC(  0x00BC,  0x00BE ),
+    AF_UNIRANGE_REC(  0x02B9,  0x02DF ),
+    AF_UNIRANGE_REC(  0x02E5,  0x02FF ),
+    AF_UNIRANGE_REC(  0x0300,  0x036F ),
+    AF_UNIRANGE_REC(  0x1AB0,  0x1ABE ),
+    AF_UNIRANGE_REC(  0x1DC0,  0x1DFF ),
+    AF_UNIRANGE_REC(  0x2017,  0x2017 ),
+    AF_UNIRANGE_REC(  0x203E,  0x203E ),
+    AF_UNIRANGE_REC(  0xA788,  0xA788 ),
+    AF_UNIRANGE_REC(  0xA7F8,  0xA7FA ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_latb_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1D62,  0x1D6A ),  /* some small subscript letters   */
+    AF_UNIRANGE_REC(  0x2080,  0x209C ),  /* subscript digits and letters   */
+    AF_UNIRANGE_REC(  0x2C7C,  0x2C7C ),  /* latin subscript small letter j */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_latb_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_latp_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x00AA,  0x00AA ),  /* feminine ordinal indicator          */
+    AF_UNIRANGE_REC(  0x00B2,  0x00B3 ),  /* superscript two and three           */
+    AF_UNIRANGE_REC(  0x00B9,  0x00BA ),  /* superscript one, masc. ord. indic.  */
+    AF_UNIRANGE_REC(  0x02B0,  0x02B8 ),  /* some latin superscript mod. letters */
+    AF_UNIRANGE_REC(  0x02E0,  0x02E4 ),  /* some IPA modifier letters           */
+    AF_UNIRANGE_REC(  0x1D2C,  0x1D61 ),  /* latin superscript modifier letters  */
+    AF_UNIRANGE_REC(  0x1D78,  0x1D78 ),  /* modifier letter cyrillic en         */
+    AF_UNIRANGE_REC(  0x1D9B,  0x1DBF ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(  0x2070,  0x207F ),  /* superscript digits and letters      */
+    AF_UNIRANGE_REC(  0x2C7D,  0x2C7D ),  /* modifier letter capital v           */
+    AF_UNIRANGE_REC(  0xA770,  0xA770 ),  /* modifier letter us                  */
+    AF_UNIRANGE_REC(  0xA7F8,  0xA7F9 ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(  0xAB5C,  0xAB5F ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_latp_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_mlym_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0D00UL,  0x0D7FUL ),  /* Malayalam */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0D00,  0x0D7F ),  /* Malayalam */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_orya_uniranges[] =
+  const AF_Script_UniRangeRec  af_mlym_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0B00UL,  0x0B7FUL ),  /* Oriya */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0D01,  0x0D01 ),
+    AF_UNIRANGE_REC(  0x0D4D,  0x0D4E ),
+    AF_UNIRANGE_REC(  0x0D62,  0x0D63 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+
+  const AF_Script_UniRangeRec  af_mymr_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0x1000, 0x109F ),    /* Myanmar            */
+    AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ),    /* Myanmar Extended-B */
+    AF_UNIRANGE_REC( 0xAA60, 0xAA7F ),    /* Myanmar Extended-A */
+    AF_UNIRANGE_REC(      0,      0 )
+  };
+
+  const AF_Script_UniRangeRec  af_mymr_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0x102D, 0x1030 ),
+    AF_UNIRANGE_REC( 0x1032, 0x1037 ),
+    AF_UNIRANGE_REC( 0x103A, 0x103A ),
+    AF_UNIRANGE_REC( 0x103D, 0x103E ),
+    AF_UNIRANGE_REC( 0x1058, 0x1059 ),
+    AF_UNIRANGE_REC( 0x105E, 0x1060 ),
+    AF_UNIRANGE_REC( 0x1071, 0x1074 ),
+    AF_UNIRANGE_REC( 0x1082, 0x1082 ),
+    AF_UNIRANGE_REC( 0x1085, 0x1086 ),
+    AF_UNIRANGE_REC( 0x108D, 0x108D ),
+    AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ),
+    AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ),
+    AF_UNIRANGE_REC(      0,      0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_none_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+  const AF_Script_UniRangeRec  af_none_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_sinh_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0D80UL,  0x0DFFUL ),  /* Sinhala */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0D80,  0x0DFF ),  /* Sinhala */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_sund_uniranges[] =
+  const AF_Script_UniRangeRec  af_sinh_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1B80UL,  0x1BBFUL ),  /* Sundanese */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0DCA,  0x0DCA ),
+    AF_UNIRANGE_REC(  0x0DD2,  0x0DD6 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_sylo_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0xA800UL,  0xA82FUL ),  /* Syloti Nagri */
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
 
   const AF_Script_UniRangeRec  af_taml_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0B80UL,  0x0BFFUL ),  /* Tamil */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0B80,  0x0BFF ),  /* Tamil */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+  const AF_Script_UniRangeRec  af_taml_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0B82,  0x0B82 ),
+    AF_UNIRANGE_REC(  0x0BC0,  0x0BC2 ),
+    AF_UNIRANGE_REC(  0x0BCD,  0x0BCD ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_telu_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C00UL,  0x0C7FUL ),  /* Telugu */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C00,  0x0C7F ),  /* Telugu */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
+  const AF_Script_UniRangeRec  af_telu_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0C00,  0x0C00 ),
+    AF_UNIRANGE_REC(  0x0C3E,  0x0C40 ),
+    AF_UNIRANGE_REC(  0x0C46,  0x0C56 ),
+    AF_UNIRANGE_REC(  0x0C62,  0x0C63 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_thai_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0E00,  0x0E7F ),  /* Thai */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_thai_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0E31,  0x0E31 ),
+    AF_UNIRANGE_REC(  0x0E34,  0x0E3A ),
+    AF_UNIRANGE_REC(  0x0E47,  0x0E4E ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+  const AF_Script_UniRangeRec  af_limb_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1900,  0x194F ),  /* Limbu */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_limb_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1920,  0x1922 ),
+    AF_UNIRANGE_REC(  0x1927,  0x1934 ),
+    AF_UNIRANGE_REC(  0x1937,  0x193B ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_orya_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0B00,  0x0B7F ),  /* Oriya */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_orya_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0B01,  0x0B02 ),
+    AF_UNIRANGE_REC(  0x0B3C,  0x0B3C ),
+    AF_UNIRANGE_REC(  0x0B3F,  0x0B3F ),
+    AF_UNIRANGE_REC(  0x0B41,  0x0B44 ),
+    AF_UNIRANGE_REC(  0x0B4D,  0x0B56 ),
+    AF_UNIRANGE_REC(  0x0B62,  0x0B63 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_sund_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1B80,  0x1BBF ),  /* Sundanese            */
+    AF_UNIRANGE_REC(  0x1CC0,  0x1CCF ),  /* Sundanese Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_sund_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1B80,  0x1B82 ),
+    AF_UNIRANGE_REC(  0x1BA1,  0x1BAD ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_sylo_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0xA800,  0xA82F ),  /* Syloti Nagri */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_sylo_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0xA802,  0xA802 ),
+    AF_UNIRANGE_REC(  0xA806,  0xA806 ),
+    AF_UNIRANGE_REC(  0xA80B,  0xA80B ),
+    AF_UNIRANGE_REC(  0xA825,  0xA826 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
   const AF_Script_UniRangeRec  af_tibt_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0F00UL,  0x0FFFUL ),  /* Tibetan */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0F00,  0x0FFF ),  /* Tibetan */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_tibt_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0F18,  0x0F19 ),
+    AF_UNIRANGE_REC(  0x0F35,  0x0F35 ),
+    AF_UNIRANGE_REC(  0x0F37,  0x0F37 ),
+    AF_UNIRANGE_REC(  0x0F39,  0x0F39 ),
+    AF_UNIRANGE_REC(  0x0F3E,  0x0F3F ),
+    AF_UNIRANGE_REC(  0x0F71,  0x0F7E ),
+    AF_UNIRANGE_REC(  0x0F80,  0x0F84 ),
+    AF_UNIRANGE_REC(  0x0F86,  0x0F87 ),
+    AF_UNIRANGE_REC(  0x0F8D,  0x0FBC ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 #endif /* !AF_CONFIG_OPTION_INDIC */
@@ -170,39 +669,44 @@
 
   const AF_Script_UniRangeRec  af_hani_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1100UL,  0x11FFUL ),  /* Hangul Jamo                             */
-    AF_UNIRANGE_REC(  0x2E80UL,  0x2EFFUL ),  /* CJK Radicals Supplement                 */
-    AF_UNIRANGE_REC(  0x2F00UL,  0x2FDFUL ),  /* Kangxi Radicals                         */
-    AF_UNIRANGE_REC(  0x2FF0UL,  0x2FFFUL ),  /* Ideographic Description Characters      */
-    AF_UNIRANGE_REC(  0x3000UL,  0x303FUL ),  /* CJK Symbols and Punctuation             */
-    AF_UNIRANGE_REC(  0x3040UL,  0x309FUL ),  /* Hiragana                                */
-    AF_UNIRANGE_REC(  0x30A0UL,  0x30FFUL ),  /* Katakana                                */
-    AF_UNIRANGE_REC(  0x3100UL,  0x312FUL ),  /* Bopomofo                                */
-    AF_UNIRANGE_REC(  0x3130UL,  0x318FUL ),  /* Hangul Compatibility Jamo               */
-    AF_UNIRANGE_REC(  0x3190UL,  0x319FUL ),  /* Kanbun                                  */
-    AF_UNIRANGE_REC(  0x31A0UL,  0x31BFUL ),  /* Bopomofo Extended                       */
-    AF_UNIRANGE_REC(  0x31C0UL,  0x31EFUL ),  /* CJK Strokes                             */
-    AF_UNIRANGE_REC(  0x31F0UL,  0x31FFUL ),  /* Katakana Phonetic Extensions            */
-    AF_UNIRANGE_REC(  0x3200UL,  0x32FFUL ),  /* Enclosed CJK Letters and Months         */
-    AF_UNIRANGE_REC(  0x3300UL,  0x33FFUL ),  /* CJK Compatibility                       */
-    AF_UNIRANGE_REC(  0x3400UL,  0x4DBFUL ),  /* CJK Unified Ideographs Extension A      */
-    AF_UNIRANGE_REC(  0x4DC0UL,  0x4DFFUL ),  /* Yijing Hexagram Symbols                 */
-    AF_UNIRANGE_REC(  0x4E00UL,  0x9FFFUL ),  /* CJK Unified Ideographs                  */
-    AF_UNIRANGE_REC(  0xA960UL,  0xA97FUL ),  /* Hangul Jamo Extended-A                  */
-    AF_UNIRANGE_REC(  0xAC00UL,  0xD7AFUL ),  /* Hangul Syllables                        */
-    AF_UNIRANGE_REC(  0xD7B0UL,  0xD7FFUL ),  /* Hangul Jamo Extended-B                  */
-    AF_UNIRANGE_REC(  0xF900UL,  0xFAFFUL ),  /* CJK Compatibility Ideographs            */
-    AF_UNIRANGE_REC(  0xFE10UL,  0xFE1FUL ),  /* Vertical forms                          */
-    AF_UNIRANGE_REC(  0xFE30UL,  0xFE4FUL ),  /* CJK Compatibility Forms                 */
-    AF_UNIRANGE_REC(  0xFF00UL,  0xFFEFUL ),  /* Halfwidth and Fullwidth Forms           */
-    AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ),  /* Kana Supplement                         */
-    AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ),  /* Tai Xuan Hing Symbols                   */
-    AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ),  /* Enclosed Ideographic Supplement         */
-    AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ),  /* CJK Unified Ideographs Extension B      */
-    AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ),  /* CJK Unified Ideographs Extension C      */
-    AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ),  /* CJK Unified Ideographs Extension D      */
-    AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ),  /* CJK Compatibility Ideographs Supplement */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1100,  0x11FF ),  /* Hangul Jamo                             */
+    AF_UNIRANGE_REC(  0x2E80,  0x2EFF ),  /* CJK Radicals Supplement                 */
+    AF_UNIRANGE_REC(  0x2F00,  0x2FDF ),  /* Kangxi Radicals                         */
+    AF_UNIRANGE_REC(  0x2FF0,  0x2FFF ),  /* Ideographic Description Characters      */
+    AF_UNIRANGE_REC(  0x3000,  0x303F ),  /* CJK Symbols and Punctuation             */
+    AF_UNIRANGE_REC(  0x3040,  0x309F ),  /* Hiragana                                */
+    AF_UNIRANGE_REC(  0x30A0,  0x30FF ),  /* Katakana                                */
+    AF_UNIRANGE_REC(  0x3100,  0x312F ),  /* Bopomofo                                */
+    AF_UNIRANGE_REC(  0x3130,  0x318F ),  /* Hangul Compatibility Jamo               */
+    AF_UNIRANGE_REC(  0x3190,  0x319F ),  /* Kanbun                                  */
+    AF_UNIRANGE_REC(  0x31A0,  0x31BF ),  /* Bopomofo Extended                       */
+    AF_UNIRANGE_REC(  0x31C0,  0x31EF ),  /* CJK Strokes                             */
+    AF_UNIRANGE_REC(  0x31F0,  0x31FF ),  /* Katakana Phonetic Extensions            */
+    AF_UNIRANGE_REC(  0x3300,  0x33FF ),  /* CJK Compatibility                       */
+    AF_UNIRANGE_REC(  0x3400,  0x4DBF ),  /* CJK Unified Ideographs Extension A      */
+    AF_UNIRANGE_REC(  0x4DC0,  0x4DFF ),  /* Yijing Hexagram Symbols                 */
+    AF_UNIRANGE_REC(  0x4E00,  0x9FFF ),  /* CJK Unified Ideographs                  */
+    AF_UNIRANGE_REC(  0xA960,  0xA97F ),  /* Hangul Jamo Extended-A                  */
+    AF_UNIRANGE_REC(  0xAC00,  0xD7AF ),  /* Hangul Syllables                        */
+    AF_UNIRANGE_REC(  0xD7B0,  0xD7FF ),  /* Hangul Jamo Extended-B                  */
+    AF_UNIRANGE_REC(  0xF900,  0xFAFF ),  /* CJK Compatibility Ideographs            */
+    AF_UNIRANGE_REC(  0xFE10,  0xFE1F ),  /* Vertical forms                          */
+    AF_UNIRANGE_REC(  0xFE30,  0xFE4F ),  /* CJK Compatibility Forms                 */
+    AF_UNIRANGE_REC(  0xFF00,  0xFFEF ),  /* Halfwidth and Fullwidth Forms           */
+    AF_UNIRANGE_REC( 0x1B000, 0x1B0FF ),  /* Kana Supplement                         */
+    AF_UNIRANGE_REC( 0x1D300, 0x1D35F ),  /* Tai Xuan Hing Symbols                   */
+    AF_UNIRANGE_REC( 0x20000, 0x2A6DF ),  /* CJK Unified Ideographs Extension B      */
+    AF_UNIRANGE_REC( 0x2A700, 0x2B73F ),  /* CJK Unified Ideographs Extension C      */
+    AF_UNIRANGE_REC( 0x2B740, 0x2B81F ),  /* CJK Unified Ideographs Extension D      */
+    AF_UNIRANGE_REC( 0x2F800, 0x2FA1F ),  /* CJK Compatibility Ideographs Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_hani_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x302A,  0x302F ),
+    AF_UNIRANGE_REC(  0x3190,  0x319F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 #endif /* !AF_CONFIG_OPTION_CJK */
diff --git a/src/autofit/afranges.h b/src/autofit/afranges.h
index fe5b2aa..1a0e4b1 100644
--- a/src/autofit/afranges.h
+++ b/src/autofit/afranges.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter Unicode script ranges (specification).                   */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFRANGES_H__
-#define __AFRANGES_H__
+#ifndef AFRANGES_H_
+#define AFRANGES_H_
 
 
 #include "aftypes.h"
@@ -26,16 +26,22 @@
 FT_BEGIN_HEADER
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 )                             \
+#define SCRIPT( s, S, d, h, H, ss )                                     \
           extern const AF_Script_UniRangeRec  af_ ## s ## _uniranges[];
 
 #include "afscript.h"
 
+#undef  SCRIPT
+#define SCRIPT( s, S, d, h, H, ss )                                             \
+          extern const AF_Script_UniRangeRec  af_ ## s ## _nonbase_uniranges[];
+
+#include "afscript.h"
+
  /* */
 
 FT_END_HEADER
 
-#endif /* __AFRANGES_H__ */
+#endif /* AFRANGES_H_ */
 
 
 /* END */
diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
index a418b05..cffe591 100644
--- a/src/autofit/afscript.h
+++ b/src/autofit/afscript.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter scripts (specification only).                            */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,103 +25,209 @@
   /* by a description string.  Then comes the corresponding HarfBuzz  */
   /* script name tag, followed by a string of standard characters (to */
   /* derive the standard width and height of stems).                  */
+  /*                                                                  */
+  /* Note that fallback scripts only have a default style, thus we    */
+  /* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for      */
+  /* them.                                                            */
+
+  SCRIPT( arab, ARAB,
+          "Arabic",
+          HB_SCRIPT_ARABIC,
+          HINTING_BOTTOM_TO_TOP,
+          "\xD9\x84 \xD8\xAD \xD9\x80" ) /* ل ح ـ */
+
+  SCRIPT( armn, ARMN,
+          "Armenian",
+          HB_SCRIPT_ARMENIAN,
+          HINTING_BOTTOM_TO_TOP,
+          "\xD5\xBD \xD5\x8D" ) /* ս Ս */
+
+  /* there are no simple forms for letters; we thus use two digit shapes */
+  SCRIPT( beng, BENG,
+          "Bengali",
+          HB_SCRIPT_BENGALI,
+          HINTING_TOP_TO_BOTTOM,
+          "\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* ০ ৪ */
+
+  SCRIPT( cher, CHER,
+          "Cherokee",
+          HB_SCRIPT_CHEROKEE,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x8E\xA4 \xE1\x8F\x85 \xEA\xAE\x95" ) /* Ꭴ Ꮕ ꮕ */
 
   SCRIPT( cyrl, CYRL,
           "Cyrillic",
           HB_SCRIPT_CYRILLIC,
-          0x43E, 0x41E, 0x0 ) /* оО */
+          HINTING_BOTTOM_TO_TOP,
+          "\xD0\xBE \xD0\x9E" ) /* о О */
 
   SCRIPT( deva, DEVA,
           "Devanagari",
           HB_SCRIPT_DEVANAGARI,
-          0x920, 0x935, 0x91F ) /* ठ व ट */
+          HINTING_TOP_TO_BOTTOM,
+          "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */
+
+  SCRIPT( ethi, ETHI,
+          "Ethiopic",
+          HB_SCRIPT_ETHIOPIC,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x8B\x90" ) /* ዐ */
+
+  SCRIPT( geor, GEOR,
+          "Georgian (Mkhedruli)",
+          HB_SCRIPT_GEORGIAN,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90" ) /* ი ე ა */
+
+  SCRIPT( geok, GEOK,
+          "Georgian (Khutsuri)",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x82\xB6 \xE1\x82\xB1 \xE2\xB4\x99" ) /* Ⴖ Ⴑ ⴙ */
 
   SCRIPT( grek, GREK,
           "Greek",
           HB_SCRIPT_GREEK,
-          0x3BF, 0x39F, 0x0 ) /* οΟ */
-
-  SCRIPT( hebr, HEBR,
-          "Hebrew",
-          HB_SCRIPT_HEBREW,
-          0x5DD, 0x0, 0x0 ) /* ם */
-
-  SCRIPT( latn, LATN,
-          "Latin",
-          HB_SCRIPT_LATIN,
-          'o', 'O', '0' )
-
-  SCRIPT( none, NONE,
-          "no script",
-          HB_SCRIPT_INVALID,
-          0x0, 0x0, 0x0 )
-
-#ifdef AF_CONFIG_OPTION_INDIC
-
-  SCRIPT( beng, BENG,
-          "Bengali",
-          HB_SCRIPT_BENGALI,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "\xCE\xBF \xCE\x9F" ) /* ο Ο */
 
   SCRIPT( gujr, GUJR,
           "Gujarati",
           HB_SCRIPT_GUJARATI,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xAA\x9F \xE0\xAB\xA6" ) /* ટ ૦ */
 
   SCRIPT( guru, GURU,
           "Gurmukhi",
           HB_SCRIPT_GURMUKHI,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_TOP_TO_BOTTOM,
+          "\xE0\xA8\xA0 \xE0\xA8\xB0 \xE0\xA9\xA6" ) /* ਠ ਰ ੦ */
+
+  SCRIPT( hebr, HEBR,
+          "Hebrew",
+          HB_SCRIPT_HEBREW,
+          HINTING_BOTTOM_TO_TOP,
+          "\xD7\x9D" ) /* ם */
 
   SCRIPT( knda, KNDA,
           "Kannada",
           HB_SCRIPT_KANNADA,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */
 
-  SCRIPT( limb, LIMB,
-          "Limbu",
-          HB_SCRIPT_LIMBU,
-          'o', 0x0, 0x0 ) /* XXX */
+  /* only digit zero has a simple shape in the Khmer script */
+  SCRIPT( khmr, KHMR,
+          "Khmer",
+          HB_SCRIPT_KHMER,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x9F\xA0" ) /* ០ */
+
+  SCRIPT( khms, KHMS,
+          "Khmer Symbols",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */
+
+  /* only digit zero has a simple shape in the Lao script */
+  SCRIPT( lao, LAO,
+          "Lao",
+          HB_SCRIPT_LAO,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xBB\x90" ) /* ໐ */
+
+  SCRIPT( latn, LATN,
+          "Latin",
+          HB_SCRIPT_LATIN,
+          HINTING_BOTTOM_TO_TOP,
+          "o O 0" )
+
+  SCRIPT( latb, LATB,
+          "Latin Subscript Fallback",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE2\x82\x92 \xE2\x82\x80" ) /* ₒ ₀ */
+
+  SCRIPT( latp, LATP,
+          "Latin Superscript Fallback",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */
 
   SCRIPT( mlym, MLYM,
           "Malayalam",
           HB_SCRIPT_MALAYALAM,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB4\xA0 \xE0\xB4\xB1" ) /* ഠ റ */
 
-  SCRIPT( orya, ORYA,
-          "Oriya",
-          HB_SCRIPT_ORIYA,
-          'o', 0x0, 0x0 ) /* XXX */
+  SCRIPT( mymr, MYMR,
+          "Myanmar",
+          HB_SCRIPT_MYANMAR,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* ဝ င ဂ */
+
+  SCRIPT( none, NONE,
+          "no script",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "" )
 
   SCRIPT( sinh, SINH,
           "Sinhala",
           HB_SCRIPT_SINHALA,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB6\xA7" ) /* ට */
+
+  /* only digit zero has a simple (round) shape in the Tamil script */
+  SCRIPT( taml, TAML,
+          "Tamil",
+          HB_SCRIPT_TAMIL,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xAF\xA6" ) /* ௦ */
+
+  /* there are no simple forms for letters; we thus use two digit shapes */
+  SCRIPT( telu, TELU,
+          "Telugu",
+          HB_SCRIPT_TELUGU,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */
+
+  SCRIPT( thai, THAI,
+          "Thai",
+          HB_SCRIPT_THAI,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+  SCRIPT( limb, LIMB,
+          "Limbu",
+          HB_SCRIPT_LIMBU,
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
+
+  SCRIPT( orya, ORYA,
+          "Oriya",
+          HB_SCRIPT_ORIYA,
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
 
   SCRIPT( sund, SUND,
           "Sundanese",
           HB_SCRIPT_SUNDANESE,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
 
   SCRIPT( sylo, SYLO,
           "Syloti Nagri",
           HB_SCRIPT_SYLOTI_NAGRI,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( taml, TAML,
-          "Tamil",
-          HB_SCRIPT_TAMIL,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( telu, TELU,
-          "Telugu",
-          HB_SCRIPT_TELUGU,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
 
   SCRIPT( tibt, TIBT,
           "Tibetan",
           HB_SCRIPT_TIBETAN,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
 
 #endif /* AF_CONFIG_OPTION_INDIC */
 
@@ -130,7 +236,8 @@
   SCRIPT( hani, HANI,
           "CJKV ideographs",
           HB_SCRIPT_HAN,
-          0x7530, 0x56D7, 0x0 ) /* 田囗 */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE7\x94\xB0 \xE5\x9B\x97" ) /* 田 囗 */
 
 #endif /* AF_CONFIG_OPTION_CJK */
 
diff --git a/src/autofit/hbshim.c b/src/autofit/afshaper.c
similarity index 67%
rename from src/autofit/hbshim.c
rename to src/autofit/afshaper.c
index cc04815..6d13b65 100644
--- a/src/autofit/hbshim.c
+++ b/src/autofit/afshaper.c
@@ -1,10 +1,10 @@
 /***************************************************************************/
 /*                                                                         */
-/*  hbshim.c                                                               */
+/*  afshaper.c                                                             */
 /*                                                                         */
 /*    HarfBuzz interface for accessing OpenType features (body).           */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,7 +20,7 @@
 #include FT_FREETYPE_H
 #include "afglobal.h"
 #include "aftypes.h"
-#include "hbshim.h"
+#include "afshaper.h"
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
 
@@ -32,7 +32,7 @@
   /* messages during execution.                                            */
   /*                                                                       */
 #undef  FT_COMPONENT
-#define FT_COMPONENT  trace_afharfbuzz
+#define FT_COMPONENT  trace_afshaper
 
 
   /*
@@ -86,7 +86,7 @@
 
   /* load HarfBuzz script tags */
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 )  h,
+#define SCRIPT( s, S, d, h, H, ss )  h,
 
 
   static const hb_script_t  scripts[] =
@@ -96,9 +96,10 @@
 
 
   FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_Byte*        gstyles )
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles,
+                          FT_Bool         default_script )
   {
     hb_face_t*  face;
 
@@ -143,8 +144,7 @@
     /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
     /* as the second tag.  We change that to HB_TAG_NONE except for the  */
     /* default script.                                                   */
-    if ( style_class->script == globals->module->default_script &&
-         style_class->coverage == AF_COVERAGE_DEFAULT           )
+    if ( default_script )
     {
       if ( script_tags[0] == HB_TAG_NONE )
         script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
@@ -158,6 +158,11 @@
     }
     else
     {
+      /* we use non-standard tags like `khms' for special purposes;       */
+      /* HarfBuzz maps them to `DFLT', which we don't want to handle here */
+      if ( script_tags[0] == HB_OT_TAG_DEFAULT_SCRIPT )
+        goto Exit;
+
       if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
         script_tags[1] = HB_TAG_NONE;
     }
@@ -187,7 +192,7 @@
     count = 0;
 #endif
 
-    for ( idx = -1; hb_set_next( gsub_lookups, &idx ); )
+    for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
     {
 #ifdef FT_DEBUG_LEVEL_TRACE
       FT_TRACE4(( " %d", idx ));
@@ -218,7 +223,7 @@
     count = 0;
 #endif
 
-    for ( idx = -1; hb_set_next( gpos_lookups, &idx ); )
+    for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
     {
 #ifdef FT_DEBUG_LEVEL_TRACE
       FT_TRACE4(( " %d", idx ));
@@ -267,7 +272,8 @@
 
           GET_UTF8_CHAR( ch, p );
 
-          for ( idx = -1; hb_set_next( gsub_lookups, &idx ); )
+          for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups,
+                                                         &idx ); )
           {
             hb_codepoint_t  gidx = FT_Get_Char_Index( globals->face, ch );
 
@@ -329,7 +335,7 @@
      * out whether a glyph gets shifted vertically, but this is something I
      * would like to avoid if not really necessary.
      *
-     * Note that we don't follow this logic for the default coverage. 
+     * Note that we don't follow this logic for the default coverage.
      * Complex scripts like Devanagari have mandatory GPOS features to
      * position many glyph elements, using mark-to-base or mark-to-ligature
      * tables; the number of glyphs missed due to condition (b) would be far
@@ -344,7 +350,7 @@
     count = 0;
 #endif
 
-    for ( idx = -1; hb_set_next( gsub_glyphs, &idx ); )
+    for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); )
     {
 #ifdef FT_DEBUG_LEVEL_TRACE
       if ( !( count % 10 ) )
@@ -362,7 +368,7 @@
         continue;
 
       if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
-        gstyles[idx] = (FT_Byte)style_class->style;
+        gstyles[idx] = (FT_UShort)style_class->style;
 #ifdef FT_DEBUG_LEVEL_TRACE
       else
         FT_TRACE4(( "*" ));
@@ -417,88 +423,150 @@
   };
 
 
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset )
+  void*
+  af_shaper_buf_create( FT_Face  face )
   {
-    AF_StyleClass  style_class;
+    FT_UNUSED( face );
 
+    return (void*)hb_buffer_create();
+  }
+
+
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf )
+  {
+    FT_UNUSED( face );
+
+    hb_buffer_destroy( (hb_buffer_t*)buf );
+  }
+
+
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count )
+  {
+    AF_StyleClass        style_class;
     const hb_feature_t*  feature;
+    FT_Int               upem;
+    const char*          q;
+    int                  len;
 
-    FT_ULong  in_idx, out_idx;
+    hb_buffer_t*    buf = (hb_buffer_t*)buf_;
+    hb_font_t*      font;
+    hb_codepoint_t  dummy;
 
 
-    if ( !metrics )
-      return FT_THROW( Invalid_Argument );
-
-    in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );
-
+    upem        = (FT_Int)metrics->globals->face->units_per_EM;
     style_class = metrics->style_class;
+    feature     = features[style_class->coverage];
 
-    feature = features[style_class->coverage];
+    font = metrics->globals->hb_font;
+
+    /* we shape at a size of units per EM; this means font units */
+    hb_font_set_scale( font, upem, upem );
+
+    while ( *p == ' ' )
+      p++;
+
+    /* count bytes up to next space (or end of buffer) */
+    q = p;
+    while ( !( *q == ' ' || *q == '\0' ) )
+      GET_UTF8_CHAR( dummy, q );
+    len = (int)( q - p );
+
+    /* feed character(s) to the HarfBuzz buffer */
+    hb_buffer_clear_contents( buf );
+    hb_buffer_add_utf8( buf, p, len, 0, len );
+
+    /* we let HarfBuzz guess the script and writing direction */
+    hb_buffer_guess_segment_properties( buf );
+
+    /* shape buffer, which means conversion from character codes to */
+    /* glyph indices, possibly applying a feature                   */
+    hb_shape( font, buf, feature, feature ? 1 : 0 );
 
     if ( feature )
     {
-      FT_UInt  upem = metrics->globals->face->units_per_EM;
+      hb_buffer_t*  hb_buf = metrics->globals->hb_buf;
 
-      hb_font_t*    font = metrics->globals->hb_font;
-      hb_buffer_t*  buf  = hb_buffer_create();
+      unsigned int      gcount;
+      hb_glyph_info_t*  ginfo;
 
-      uint32_t  c = (uint32_t)charcode;
-
-      hb_glyph_info_t*      ginfo;
-      hb_glyph_position_t*  gpos;
-      unsigned int          gcount;
+      unsigned int      hb_gcount;
+      hb_glyph_info_t*  hb_ginfo;
 
 
-      /* we shape at a size of units per EM; this means font units */
-      hb_font_set_scale( font, upem, upem );
+      /* we have to check whether applying a feature does actually change */
+      /* glyph indices; otherwise the affected glyph or glyphs aren't     */
+      /* available at all in the feature                                  */
 
-      /* XXX: is this sufficient for a single character of any script? */
-      hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
-      hb_buffer_set_script( buf, scripts[style_class->script] );
+      hb_buffer_clear_contents( hb_buf );
+      hb_buffer_add_utf8( hb_buf, p, len, 0, len );
+      hb_buffer_guess_segment_properties( hb_buf );
+      hb_shape( font, hb_buf, NULL, 0 );
 
-      /* we add one character to `buf' ... */
-      hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
+      ginfo    = hb_buffer_get_glyph_infos( buf, &gcount );
+      hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount );
 
-      /* ... and apply one feature */
-      hb_shape( font, buf, feature, 1 );
-
-      ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
-      gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
-
-      out_idx = ginfo[0].codepoint;
-
-      /* getting the same index indicates no substitution,         */
-      /* which means that the glyph isn't available in the feature */
-      if ( in_idx == out_idx )
+      if ( gcount == hb_gcount )
       {
-        *codepoint = 0;
-        *y_offset  = 0;
-      }
-      else
-      {
-        *codepoint = out_idx;
-        *y_offset  = gpos[0].y_offset;
-      }
+        unsigned int  i;
 
-      hb_buffer_destroy( buf );
+
+        for (i = 0; i < gcount; i++ )
+          if ( ginfo[i].codepoint != hb_ginfo[i].codepoint )
+            break;
+
+        if ( i == gcount )
+        {
+          /* both buffers have identical glyph indices */
+          hb_buffer_clear_contents( buf );
+        }
+      }
+    }
+
+    *count = hb_buffer_get_length( buf );
 
 #ifdef FT_DEBUG_LEVEL_TRACE
-      if ( gcount > 1 )
-        FT_TRACE1(( "af_get_char_index:"
-                    " input character mapped to multiple glyphs\n" ));
+    if ( feature && *count > 1 )
+      FT_TRACE1(( "af_shaper_get_cluster:"
+                  " input character mapped to multiple glyphs\n" ));
 #endif
-    }
-    else
-    {
-      *codepoint = in_idx;
-      *y_offset  = 0;
-    }
 
-    return FT_Err_Ok;
+    return q;
+  }
+
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         advance,
+                      FT_Long*         y_offset )
+  {
+    hb_buffer_t*          buf = (hb_buffer_t*)buf_;
+    hb_glyph_info_t*      ginfo;
+    hb_glyph_position_t*  gpos;
+    unsigned int          gcount;
+
+    FT_UNUSED( metrics );
+
+
+    ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+    gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
+
+    if ( idx >= gcount )
+      return 0;
+
+    if ( advance )
+      *advance = gpos[idx].x_advance;
+    if ( y_offset )
+      *y_offset = gpos[idx].y_offset;
+
+    return ginfo[idx].codepoint;
   }
 
 
@@ -506,36 +574,106 @@
 
 
   FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_Byte*        gstyles )
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles,
+                          FT_Bool         default_script )
   {
     FT_UNUSED( globals );
     FT_UNUSED( style_class );
     FT_UNUSED( gstyles );
+    FT_UNUSED( default_script );
 
     return FT_Err_Ok;
   }
 
 
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset )
+  void*
+  af_shaper_buf_create( FT_Face  face )
   {
-    FT_Face  face;
+    FT_Error   error;
+    FT_Memory  memory = face->memory;
+    FT_ULong*  buf;
 
 
-    if ( !metrics )
-      return FT_THROW( Invalid_Argument );
+    FT_MEM_ALLOC( buf, sizeof ( FT_ULong ) );
 
-    face = metrics->globals->face;
+    return (void*)buf;
+  }
 
-    *codepoint = FT_Get_Char_Index( face, charcode );
-    *y_offset  = 0;
 
-    return FT_Err_Ok;
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf )
+  {
+    FT_Memory  memory = face->memory;
+
+
+    FT_FREE( buf );
+  }
+
+
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count )
+  {
+    FT_Face    face      = metrics->globals->face;
+    FT_ULong   ch, dummy = 0;
+    FT_ULong*  buf       = (FT_ULong*)buf_;
+
+
+    while ( *p == ' ' )
+      p++;
+
+    GET_UTF8_CHAR( ch, p );
+
+    /* since we don't have an engine to handle clusters, */
+    /* we scan the characters but return zero            */
+    while ( !( *p == ' ' || *p == '\0' ) )
+      GET_UTF8_CHAR( dummy, p );
+
+    if ( dummy )
+    {
+      *buf   = 0;
+      *count = 0;
+    }
+    else
+    {
+      *buf   = FT_Get_Char_Index( face, ch );
+      *count = 1;
+    }
+
+    return p;
+  }
+
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         advance,
+                      FT_Long*         y_offset )
+  {
+    FT_Face   face        = metrics->globals->face;
+    FT_ULong  glyph_index = *(FT_ULong*)buf_;
+
+    FT_UNUSED( idx );
+
+
+    if ( advance )
+      FT_Get_Advance( face,
+                      glyph_index,
+                      FT_LOAD_NO_SCALE         |
+                      FT_LOAD_NO_HINTING       |
+                      FT_LOAD_IGNORE_TRANSFORM,
+                      advance );
+
+    if ( y_offset )
+      *y_offset = 0;
+
+    return glyph_index;
   }
 
 
diff --git a/src/autofit/afshaper.h b/src/autofit/afshaper.h
new file mode 100644
index 0000000..0d41f78
--- /dev/null
+++ b/src/autofit/afshaper.h
@@ -0,0 +1,72 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afshaper.h                                                             */
+/*                                                                         */
+/*    HarfBuzz interface for accessing OpenType features (specification).  */
+/*                                                                         */
+/*  Copyright 2013-2016 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 AFSHAPER_H_
+#define AFSHAPER_H_
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+#endif
+
+
+FT_BEGIN_HEADER
+
+  FT_Error
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles,
+                          FT_Bool         default_script );
+
+
+  void*
+  af_shaper_buf_create( FT_Face  face );
+
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf );
+
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count );
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         x_advance,
+                      FT_Long*         y_offset );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* AFSHAPER_H_ */
+
+
+/* END */
diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h
index 27fdd2e..e83a95b 100644
--- a/src/autofit/afstyles.h
+++ b/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter styles (specification only).                             */
 /*                                                                         */
-/*  Copyright 2013, 2014 by                                                */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,9 @@
   /* coverage.                                                     */
   /*                                                               */
   /* Note that styles using `AF_COVERAGE_DEFAULT' should always    */
-  /* come after styles with other coverages.                       */
+  /* come after styles with other coverages.  Also note that       */
+  /* fallback scripts only use `AF_COVERAGE_DEFAULT' for its       */
+  /* style.                                                        */
   /*                                                               */
   /* Example:                                                      */
   /*                                                               */
@@ -50,10 +52,10 @@
 #undef  META_STYLE_LATIN
 #define META_STYLE_LATIN( s, S, ds )                     \
           STYLE_LATIN( s, S, c2cp, C2CP, ds,             \
-                       "petite capticals from capitals", \
+                       "petite capitals from capitals", \
                        PETITE_CAPITALS_FROM_CAPITALS )   \
           STYLE_LATIN( s, S, c2sc, C2SC, ds,             \
-                       "small capticals from capitals",  \
+                       "small capitals from capitals",  \
                        SMALL_CAPITALS_FROM_CAPITALS )    \
           STYLE_LATIN( s, S, ordn, ORDN, ds,             \
                        "ordinals",                       \
@@ -80,23 +82,130 @@
                        "default",                        \
                        DEFAULT )
 
+
+  STYLE( arab_dflt, ARAB_DFLT,
+         "Arabic default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_ARAB,
+         AF_BLUE_STRINGSET_ARAB,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( armn_dflt, ARMN_DFLT,
+         "Armenian default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_ARMN,
+         AF_BLUE_STRINGSET_ARMN,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( beng_dflt, BENG_DFLT,
+         "Bengali default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_BENG,
+         AF_BLUE_STRINGSET_BENG,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( cher_dflt, CHER_DFLT,
+         "Cherokee default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_CHER,
+         AF_BLUE_STRINGSET_CHER,
+         AF_COVERAGE_DEFAULT )
+
   META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
 
+  STYLE( deva_dflt, DEVA_DFLT,
+         "Devanagari default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_DEVA,
+         AF_BLUE_STRINGSET_DEVA,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( ethi_dflt, ETHI_DFLT,
+         "Ethiopic default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_ETHI,
+         AF_BLUE_STRINGSET_ETHI,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( geor_dflt, GEOR_DFLT,
+         "Georgian (Mkhedruli) default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GEOR,
+         AF_BLUE_STRINGSET_GEOR,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( geok_dflt, GEOK_DFLT,
+         "Georgian (Khutsuri) default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GEOK,
+         AF_BLUE_STRINGSET_GEOK,
+         AF_COVERAGE_DEFAULT )
+
   META_STYLE_LATIN( grek, GREK, "Greek" )
 
+  STYLE( gujr_dflt, GUJR_DFLT,
+         "Gujarati default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GUJR,
+         AF_BLUE_STRINGSET_GUJR,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( guru_dflt, GURU_DFLT,
+         "Gurmukhi default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GURU,
+         AF_BLUE_STRINGSET_GURU,
+         AF_COVERAGE_DEFAULT )
+
   STYLE( hebr_dflt, HEBR_DFLT,
          "Hebrew default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_SCRIPT_HEBR,
          AF_BLUE_STRINGSET_HEBR,
          AF_COVERAGE_DEFAULT )
+
+  STYLE( knda_dflt, KNDA_DFLT,
+         "Kannada default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_KNDA,
+         AF_BLUE_STRINGSET_KNDA,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( khmr_dflt, KHMR_DFLT,
+         "Khmer default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_KHMR,
+         AF_BLUE_STRINGSET_KHMR,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( khms_dflt, KHMS_DFLT,
+         "Khmer Symbols default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_KHMS,
+         AF_BLUE_STRINGSET_KHMS,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( lao_dflt, LAO_DFLT,
+         "Lao default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_LAO,
+         AF_BLUE_STRINGSET_LAO,
+         AF_COVERAGE_DEFAULT )
+
   META_STYLE_LATIN( latn, LATN, "Latin" )
 
-  STYLE( deva_dflt, DEVA_DFLT,
-         "Devanagari default style",
+  STYLE( latb_dflt, LATB_DFLT,
+         "Latin subscript fallback default style",
          AF_WRITING_SYSTEM_LATIN,
-         AF_SCRIPT_DEVA,
-         AF_BLUE_STRINGSET_DEVA,
+         AF_SCRIPT_LATB,
+         AF_BLUE_STRINGSET_LATB,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( latp_dflt, LATP_DFLT,
+         "Latin superscript fallback default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_LATP,
+         AF_BLUE_STRINGSET_LATP,
          AF_COVERAGE_DEFAULT )
 
 #ifdef FT_OPTION_AUTOFIT2
@@ -108,11 +217,53 @@
          AF_COVERAGE_DEFAULT )
 #endif
 
+  STYLE( mlym_dflt, MLYM_DFLT,
+         "Malayalam default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_MLYM,
+         AF_BLUE_STRINGSET_MLYM,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( mymr_dflt, MYMR_DFLT,
+         "Myanmar default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_MYMR,
+         AF_BLUE_STRINGSET_MYMR,
+         AF_COVERAGE_DEFAULT )
+
   STYLE( none_dflt, NONE_DFLT,
          "no style",
          AF_WRITING_SYSTEM_DUMMY,
          AF_SCRIPT_NONE,
-         (AF_Blue_Stringset)0,
+         AF_BLUE_STRINGSET_NONE,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( sinh_dflt, SINH_DFLT,
+         "Sinhala default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_SINH,
+         AF_BLUE_STRINGSET_SINH,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( taml_dflt, TAML_DFLT,
+         "Tamil default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_TAML,
+         AF_BLUE_STRINGSET_TAML,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( telu_dflt, TELU_DFLT,
+         "Telugu default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_TELU,
+         AF_BLUE_STRINGSET_TELU,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( thai_dflt, THAI_DFLT,
+         "Thai default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_THAI,
+         AF_BLUE_STRINGSET_THAI,
          AF_COVERAGE_DEFAULT )
 
 #ifdef AF_CONFIG_OPTION_INDIC
@@ -127,18 +278,10 @@
                  (AF_Blue_Stringset)0,    \
                  AF_COVERAGE_DEFAULT )
 
-  STYLE_DEFAULT_INDIC( beng, BENG, "Bengali" )
-  STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" )
-  STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" )
-  STYLE_DEFAULT_INDIC( knda, KNDA, "Kannada" )
   STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" )
-  STYLE_DEFAULT_INDIC( mlym, MLYM, "Malayalam" )
   STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" )
-  STYLE_DEFAULT_INDIC( sinh, SINH, "Sinhala" )
   STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" )
   STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" )
-  STYLE_DEFAULT_INDIC( taml, TAML, "Tamil" )
-  STYLE_DEFAULT_INDIC( telu, TELU, "Telugu" )
   STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" )
 
 #endif /* AF_CONFIG_OPTION_INDIC */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 61badd1..ef62043 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter types (specification only).                              */
 /*                                                                         */
-/*  Copyright 2003-2009, 2011-2014 by                                      */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,15 +22,15 @@
    *  Its main feature is the ability to differentiate between different
    *  writing systems and scripts in order to apply specific rules.
    *
-   *  The code has also been compartmentized into several entities that
+   *  The code has also been compartmentalized into several entities that
    *  should make algorithmic experimentation easier than with the old
    *  code.
    *
    *************************************************************************/
 
 
-#ifndef __AFTYPES_H__
-#define __AFTYPES_H__
+#ifndef AFTYPES_H_
+#define AFTYPES_H_
 
 #include <ft2build.h>
 
@@ -41,6 +41,10 @@
 
 #include "afblue.h"
 
+#ifdef FT_DEBUG_AUTOFIT
+#include FT_CONFIG_STANDARD_LIBRARY_H
+#endif
+
 
 FT_BEGIN_HEADER
 
@@ -54,8 +58,6 @@
 
 #ifdef FT_DEBUG_AUTOFIT
 
-#include FT_CONFIG_STANDARD_LIBRARY_H
-
 extern int    _af_debug_disable_horz_hints;
 extern int    _af_debug_disable_vert_hints;
 extern int    _af_debug_disable_blue_hints;
@@ -138,11 +140,10 @@
     AF_Angle  _delta = (angle2) - (angle1);     \
                                                 \
                                                 \
-    _delta %= AF_ANGLE_2PI;                     \
-    if ( _delta < 0 )                           \
+    while ( _delta <= -AF_ANGLE_PI )            \
       _delta += AF_ANGLE_2PI;                   \
                                                 \
-    if ( _delta > AF_ANGLE_PI )                 \
+    while ( _delta > AF_ANGLE_PI )              \
       _delta -= AF_ANGLE_2PI;                   \
                                                 \
     result = _delta;                            \
@@ -168,13 +169,10 @@
    *  auto-hinted glyph image.
    */
 
-  typedef enum  AF_ScalerFlags_
-  {
-    AF_SCALER_FLAG_NO_HORIZONTAL = 1,  /* disable horizontal hinting */
-    AF_SCALER_FLAG_NO_VERTICAL   = 2,  /* disable vertical hinting   */
-    AF_SCALER_FLAG_NO_ADVANCE    = 4   /* disable advance hinting    */
-
-  } AF_ScalerFlags;
+#define AF_SCALER_FLAG_NO_HORIZONTAL  1U /* disable horizontal hinting */
+#define AF_SCALER_FLAG_NO_VERTICAL    2U /* disable vertical hinting   */
+#define AF_SCALER_FLAG_NO_ADVANCE     4U /* disable advance hinting    */
+#define AF_SCALER_FLAG_NO_WARPER      8U /* disable warper             */
 
 
   typedef struct  AF_ScalerRec_
@@ -213,13 +211,19 @@
   typedef void
   (*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics  metrics );
 
+  typedef void
+  (*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics  metrics,
+                                        FT_Pos*          stdHW,
+                                        FT_Pos*          stdVW );
+
 
   typedef FT_Error
   (*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints    hints,
                                      AF_StyleMetrics  metrics );
 
   typedef void
-  (*AF_WritingSystem_ApplyHintsFunc)( AF_GlyphHints    hints,
+  (*AF_WritingSystem_ApplyHintsFunc)( FT_UInt          glyph_index,
+                                      AF_GlyphHints    hints,
                                       FT_Outline*      outline,
                                       AF_StyleMetrics  metrics );
 
@@ -251,7 +255,7 @@
    *    outline according to the results of the glyph analyzer.
    */
 
-#define __AFWRTSYS_H__  /* don't load header files */
+#define AFWRTSYS_H_  /* don't load header files */
 #undef  WRITING_SYSTEM
 #define WRITING_SYSTEM( ws, WS )    \
           AF_WRITING_SYSTEM_ ## WS,
@@ -266,7 +270,7 @@
 
   } AF_WritingSystem;
 
-#undef  __AFWRTSYS_H__
+#undef  AFWRTSYS_H_
 
 
   typedef struct  AF_WritingSystemClassRec_
@@ -277,6 +281,7 @@
     AF_WritingSystem_InitMetricsFunc   style_metrics_init;
     AF_WritingSystem_ScaleMetricsFunc  style_metrics_scale;
     AF_WritingSystem_DoneMetricsFunc   style_metrics_done;
+    AF_WritingSystem_GetStdWidthsFunc  style_metrics_getstdw;
 
     AF_WritingSystem_InitHintsFunc     style_hints_init;
     AF_WritingSystem_ApplyHintsFunc    style_hints_apply;
@@ -295,15 +300,16 @@
   /*************************************************************************/
 
   /*
-   *  Each script is associated with a set of Unicode ranges that gets used
-   *  to test whether the font face supports the script.
+   *  Each script is associated with two sets of Unicode ranges to test
+   *  whether the font face supports the script, and which non-base
+   *  characters the script contains.
    *
    *  We use four-letter script tags from the OpenType specification,
    *  extended by `NONE', which indicates `no script'.
    */
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, H, ss ) \
           AF_SCRIPT_ ## S,
 
   /* The list of known scripts. */
@@ -333,11 +339,13 @@
   {
     AF_Script  script;
 
-    AF_Script_UniRange  script_uni_ranges; /* last must be { 0, 0 }        */
+    /* last element in the ranges must be { 0, 0 } */
+    AF_Script_UniRange  script_uni_ranges;
+    AF_Script_UniRange  script_uni_nonbase_ranges;
 
-    FT_UInt32  standard_char1;             /* for default width and height */
-    FT_UInt32  standard_char2;             /* ditto                        */
-    FT_UInt32  standard_char3;             /* ditto                        */
+    FT_Bool  top_to_bottom_hinting;
+
+    const char*  standard_charstring;      /* for default width and height */
 
   } AF_ScriptClassRec;
 
@@ -473,6 +481,10 @@
   } AF_StyleMetricsRec;
 
 
+#define AF_HINTING_BOTTOM_TO_TOP  0
+#define AF_HINTING_TOP_TO_BOTTOM  1
+
+
   /* Declare and define vtables for classes */
 #ifndef FT_CONFIG_OPTION_PIC
 
@@ -487,6 +499,7 @@
           m_init,                                        \
           m_scale,                                       \
           m_done,                                        \
+          m_stdw,                                        \
           h_init,                                        \
           h_apply )                                      \
   FT_CALLBACK_TABLE_DEF                                  \
@@ -499,6 +512,7 @@
     m_init,                                              \
     m_scale,                                             \
     m_done,                                              \
+    m_stdw,                                              \
                                                          \
     h_init,                                              \
     h_apply                                              \
@@ -513,17 +527,17 @@
           script_class,                   \
           script,                         \
           ranges,                         \
-          std_char1,                      \
-          std_char2,                      \
-          std_char3 )                     \
+          nonbase_ranges,                 \
+          top_to_bottom,                  \
+          std_charstring )                \
   FT_CALLBACK_TABLE_DEF                   \
   const AF_ScriptClassRec  script_class = \
   {                                       \
     script,                               \
     ranges,                               \
-    std_char1,                            \
-    std_char2,                            \
-    std_char3                             \
+    nonbase_ranges,                       \
+    top_to_bottom,                        \
+    std_charstring,                       \
   };
 
 
@@ -566,16 +580,17 @@
   FT_LOCAL_DEF( void )                                                    \
   FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec*  ac ) \
   {                                                                       \
-    ac->writing_system      = system;                                     \
+    ac->writing_system        = system;                                   \
                                                                           \
-    ac->style_metrics_size  = m_size;                                     \
+    ac->style_metrics_size    = m_size;                                   \
                                                                           \
-    ac->style_metrics_init  = m_init;                                     \
-    ac->style_metrics_scale = m_scale;                                    \
-    ac->style_metrics_done  = m_done;                                     \
+    ac->style_metrics_init    = m_init;                                   \
+    ac->style_metrics_scale   = m_scale;                                  \
+    ac->style_metrics_done    = m_done;                                   \
+    ac->style_metrics_getstdw = m_stdw;                                   \
                                                                           \
-    ac->style_hints_init    = h_init;                                     \
-    ac->style_hints_apply   = h_apply;                                    \
+    ac->style_hints_init      = h_init;                                   \
+    ac->style_hints_apply     = h_apply;                                  \
   }
 
 
@@ -587,17 +602,17 @@
           script_class,                                    \
           script_,                                         \
           ranges,                                          \
-          std_char1,                                       \
-          std_char2,                                       \
-          std_char3 )                                      \
+          nonbase_ranges,                                  \
+          top_to_bottom,                                   \
+          std_charstring )                                 \
   FT_LOCAL_DEF( void )                                     \
   FT_Init_Class_ ## script_class( AF_ScriptClassRec*  ac ) \
   {                                                        \
-    ac->script            = script_;                       \
-    ac->script_uni_ranges = ranges;                        \
-    ac->standard_char1    = std_char1;                     \
-    ac->standard_char2    = std_char2;                     \
-    ac->standard_char3    = std_char3;                     \
+    ac->script                    = script_;               \
+    ac->script_uni_ranges         = ranges;                \
+    ac->script_uni_nonbase_ranges = nonbase_ranges;        \
+    ac->top_to_bottom_hinting     = top_to_bottom;         \
+    ac->standard_charstring       = std_charstring;        \
   }
 
 
@@ -629,7 +644,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFTYPES_H__ */
+#endif /* AFTYPES_H_ */
 
 
 /* END */
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
index 34a97ff..ce1806c 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter warping algorithm (body).                                */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2011 by                                          */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -76,10 +76,10 @@
                                FT_Pos        xx2,
                                AF_WarpScore  base_distort,
                                AF_Segment    segments,
-                               FT_UInt       num_segments )
+                               FT_Int        num_segments )
   {
     FT_Int        idx_min, idx_max, idx0;
-    FT_UInt       nn;
+    FT_Int        nn;
     AF_WarpScore  scores[65];
 
 
@@ -171,7 +171,7 @@
     FT_Fixed      org_scale;
     FT_Pos        org_delta;
 
-    FT_UInt       nn, num_points, num_segments;
+    FT_Int        nn, num_points, num_segments;
     FT_Int        X1, X2;
     FT_Int        w;
 
@@ -193,7 +193,7 @@
 
     warper->best_scale   = org_scale;
     warper->best_delta   = org_delta;
-    warper->best_score   = INT_MIN;
+    warper->best_score   = FT_INT_MIN;
     warper->best_distort = 0;
 
     axis         = &hints->axis[dim];
diff --git a/src/autofit/afwarp.h b/src/autofit/afwarp.h
index 7343fdd..6d96f86 100644
--- a/src/autofit/afwarp.h
+++ b/src/autofit/afwarp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter warping algorithm (specification).                       */
 /*                                                                         */
-/*  Copyright 2006, 2007 by                                                */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFWARP_H__
-#define __AFWARP_H__
+#ifndef AFWARP_H_
+#define AFWARP_H_
 
 #include "afhints.h"
 
@@ -25,7 +25,7 @@
 
 #define AF_WARPER_SCALE
 
-#define AF_WARPER_FLOOR( x )  ( (x) & ~63 )
+#define AF_WARPER_FLOOR( x )  ( (x) & ~FT_TYPEOF( x )63 )
 #define AF_WARPER_CEIL( x )   AF_WARPER_FLOOR( (x) + 63 )
 
 
@@ -58,7 +58,7 @@
 FT_END_HEADER
 
 
-#endif /* __AFWARP_H__ */
+#endif /* AFWARP_H_ */
 
 
 /* END */
diff --git a/src/autofit/afwrtsys.h b/src/autofit/afwrtsys.h
index 8aa2ed9..842f492 100644
--- a/src/autofit/afwrtsys.h
+++ b/src/autofit/afwrtsys.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter writing systems (specification only).                    */
 /*                                                                         */
-/*  Copyright 2013 by                                                      */
+/*  Copyright 2013-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __AFWRTSYS_H__
-#define __AFWRTSYS_H__
+#ifndef AFWRTSYS_H_
+#define AFWRTSYS_H_
 
   /* Since preprocessor directives can't create other preprocessor */
   /* directives, we have to include the header files manually.     */
@@ -30,7 +30,7 @@
 #include "aflatin2.h"
 #endif
 
-#endif /* __AFWRTSYS_H__ */
+#endif /* AFWRTSYS_H_ */
 
 
   /* The following part can be included multiple times. */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index e2b9934..dda9aeb 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module (body).                                           */
 /*                                                                         */
-/*  Copyright 2003-2007, 2011, 2013 by                                     */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -34,7 +34,7 @@
 #include "afcjk.c"
 #include "afindic.c"
 
-#include "hbshim.c"
+#include "afshaper.c"
 
 #include "afloader.c"
 #include "afmodule.c"
diff --git a/src/autofit/hbshim.h b/src/autofit/hbshim.h
deleted file mode 100644
index 02f1513..0000000
--- a/src/autofit/hbshim.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  hbshim.h                                                               */
-/*                                                                         */
-/*    HarfBuzz interface for accessing OpenType features (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 __HBSHIM_H__
-#define __HBSHIM_H__
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-
-#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
-
-#include <hb.h>
-#include <hb-ot.h>
-#include <hb-ft.h>
-
-#endif
-
-
-FT_BEGIN_HEADER
-
-  FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_Byte*        gstyles );
-
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset );
-
- /* */
-
-FT_END_HEADER
-
-#endif /* __HBSHIM_H__ */
-
-
-/* END */
diff --git a/src/base/basepic.c b/src/base/basepic.c
index aeb6fd5..f2cea90 100644
--- a/src/base/basepic.c
+++ b/src/base/basepic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for base.            */
 /*                                                                         */
-/*  Copyright 2009, 2012, 2013 by                                          */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/base/basepic.h b/src/base/basepic.h
index 329d7c8..a1a75a0 100644
--- a/src/base/basepic.h
+++ b/src/base/basepic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for base.            */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,14 +16,13 @@
 /***************************************************************************/
 
 
-#ifndef __BASEPIC_H__
-#define __BASEPIC_H__
+#ifndef BASEPIC_H_
+#define BASEPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
 #define FT_OUTLINE_GLYPH_CLASS_GET  &ft_outline_glyph_class
@@ -43,6 +42,8 @@
 #endif
 
 
+FT_BEGIN_HEADER
+
   typedef struct  BasePIC_
   {
     FT_Module_Class**  default_module_classes;
@@ -78,13 +79,13 @@
   FT_Error
   ft_base_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
   /* */
 
-FT_END_HEADER
-
-#endif /* __BASEPIC_H__ */
+#endif /* BASEPIC_H_ */
 
 
 /* END */
diff --git a/src/base/ftadvanc.c b/src/base/ftadvanc.c
index 5207847..9e2ab89 100644
--- a/src/base/ftadvanc.c
+++ b/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (body).                          */
 /*                                                                         */
-/*  Copyright 2008, 2009, 2011, 2013 by                                    */
+/*  Copyright 2008-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -60,10 +60,12 @@
    /*  - unscaled load                                             */
    /*  - unhinted load                                             */
    /*  - light-hinted load                                         */
+   /*  - neither a MM nor a GX font                                */
 
-#define LOAD_ADVANCE_FAST_CHECK( flags )                            \
-          ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
-            FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
+#define LOAD_ADVANCE_FAST_CHECK( face, flags )                          \
+          ( ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    ||   \
+              FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT ) && \
+            !FT_HAS_MULTIPLE_MASTERS( face )                         )
 
 
   /* documentation is in ftadvanc.h */
@@ -80,11 +82,14 @@
     if ( !face )
       return FT_THROW( Invalid_Face_Handle );
 
+    if ( !padvance )
+      return FT_THROW( Invalid_Argument );
+
     if ( gindex >= (FT_UInt)face->num_glyphs )
       return FT_THROW( Invalid_Glyph_Index );
 
     func = face->driver->clazz->get_advances;
-    if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
+    if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
     {
       FT_Error  error;
 
@@ -118,6 +123,9 @@
     if ( !face )
       return FT_THROW( Invalid_Face_Handle );
 
+    if ( !padvances )
+      return FT_THROW( Invalid_Argument );
+
     num = (FT_UInt)face->num_glyphs;
     end = start + count;
     if ( start >= num || end < start || end > num )
@@ -127,7 +135,7 @@
       return FT_Err_Ok;
 
     func = face->driver->clazz->get_advances;
-    if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
+    if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
     {
       error = func( face, start, count, flags, padvances );
       if ( !error )
@@ -151,8 +159,8 @@
 
       /* scale from 26.6 to 16.16 */
       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
-                      ? face->glyph->advance.y << 10
-                      : face->glyph->advance.x << 10;
+                      ? face->glyph->advance.y * 1024
+                      : face->glyph->advance.x * 1024;
     }
 
     return error;
diff --git a/src/base/ftapi.c b/src/base/ftapi.c
index 8914d1f..b94c3eb 100644
--- a/src/base/ftapi.c
+++ b/src/base/ftapi.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType compatibility functions (body).                         */
 /*                                                                         */
-/*  Copyright 2002 by                                                      */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/base/ftbase.c b/src/base/ftbase.c
index 5e5d70e..ab1af6f 100644
--- a/src/base/ftbase.c
+++ b/src/base/ftbase.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Single object library component (body only).                         */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by       */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,6 +26,7 @@
 #include "ftcalc.c"
 #include "ftdbgmem.c"
 #include "ftgloadr.c"
+#include "fthash.c"
 #include "ftobjs.c"
 #include "ftoutln.c"
 #include "ftrfork.c"
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index 51a1db1..717fdaa 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private functions used in base module (specification).  */
 /*                                                                         */
-/*  Copyright 2008, 2010 by                                                */
+/*  Copyright 2008-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTBASE_H__
-#define __FTBASE_H__
+#ifndef FTBASE_H_
+#define FTBASE_H_
 
 
 #include <ft2build.h>
@@ -27,6 +27,11 @@
 FT_BEGIN_HEADER
 
 
+  /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */
+  /* see https://support.microsoft.com/en-us/kb/130437                */
+#define FT_MAC_RFORK_MAX_LEN  0x00FFFFFFUL
+
+
   /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
   /* font, and try to load a face specified by the face_index.            */
   FT_LOCAL( FT_Error )
@@ -63,7 +68,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTBASE_H__ */
+#endif /* FTBASE_H_ */
 
 
 /* END */
diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
index 8d3f383..d3e45ff 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType bbox computation (body).                                    */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004, 2006, 2010, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -42,16 +42,35 @@
   } TBBox_Rec;
 
 
+#define FT_UPDATE_BBOX( p, bbox ) \
+  FT_BEGIN_STMNT                  \
+    if ( p->x < bbox.xMin )       \
+      bbox.xMin = p->x;           \
+    if ( p->x > bbox.xMax )       \
+      bbox.xMax = p->x;           \
+    if ( p->y < bbox.yMin )       \
+      bbox.yMin = p->y;           \
+    if ( p->y > bbox.yMax )       \
+      bbox.yMax = p->y;           \
+  FT_END_STMNT
+
+#define CHECK_X( p, bbox )                         \
+          ( p->x < bbox.xMin || p->x > bbox.xMax )
+
+#define CHECK_Y( p, bbox )                         \
+          ( p->y < bbox.yMin || p->y > bbox.yMax )
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
   /*    BBox_Move_To                                                       */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This function is used as a `move_to' and `line_to' emitter during  */
+  /*    This function is used as a `move_to' emitter during                */
   /*    FT_Outline_Decompose().  It simply records the destination point   */
-  /*    in `user->last'; no further computations are necessary since we    */
-  /*    use the cbox as the starting bbox which must be refined.           */
+  /*    in `user->last'. We also update bbox in case contour starts with   */
+  /*    an implicit `on' point.                                            */
   /*                                                                       */
   /* <Input>                                                               */
   /*    to   :: A pointer to the destination vector.                       */
@@ -66,17 +85,42 @@
   BBox_Move_To( FT_Vector*  to,
                 TBBox_Rec*  user )
   {
+    FT_UPDATE_BBOX( to, user->bbox );
+
     user->last = *to;
 
     return 0;
   }
 
 
-#define CHECK_X( p, bbox )  \
-          ( p->x < bbox.xMin || p->x > bbox.xMax )
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Line_To                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used as a `line_to' emitter during                */
+  /*    FT_Outline_Decompose().  It simply records the destination point   */
+  /*    in `user->last'; no further computations are necessary because     */
+  /*    bbox already contains both explicit ends of the line segment.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the destination vector.                       */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    user :: A pointer to the current walk context.                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Always 0.  Needed for the interface only.                          */
+  /*                                                                       */
+  static int
+  BBox_Line_To( FT_Vector*  to,
+                TBBox_Rec*  user )
+  {
+    user->last = *to;
 
-#define CHECK_Y( p, bbox )  \
-          ( p->y < bbox.yMin || p->y > bbox.yMax )
+    return 0;
+  }
 
 
   /*************************************************************************/
@@ -155,8 +199,8 @@
                  FT_Vector*  to,
                  TBBox_Rec*  user )
   {
-    /* we don't need to check `to' since it is always an `on' point, thus */
-    /* within the bbox                                                    */
+    /* in case `to' is implicit and not included in bbox yet */
+    FT_UPDATE_BBOX( to, user->bbox );
 
     if ( CHECK_X( control, user->bbox ) )
       BBox_Conic_Check( user->last.x,
@@ -203,15 +247,51 @@
   /*    max :: The address of the current maximum.                         */
   /*                                                                       */
   static FT_Pos
-  update_cubic_max( FT_Pos  q1,
-                    FT_Pos  q2,
-                    FT_Pos  q3,
-                    FT_Pos  q4,
-                    FT_Pos  max )
+  cubic_peak( FT_Pos  q1,
+              FT_Pos  q2,
+              FT_Pos  q3,
+              FT_Pos  q4 )
   {
-    /* 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 )
+    FT_Pos  peak = 0;
+    FT_Int  shift;
+
+
+    /* This function finds a peak of a cubic segment if it is above 0    */
+    /* using iterative bisection of the segment, or returns 0.           */
+    /* 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.             */
+    /* It is called with either q2 or q3 positive, which is necessary    */
+    /* for the peak to exist and avoids undefined FT_MSB.                */
+
+    shift = 27 - FT_MSB( (FT_UInt32)( FT_ABS( q1 ) |
+                                      FT_ABS( q2 ) |
+                                      FT_ABS( q3 ) |
+                                      FT_ABS( q4 ) ) );
+
+    if ( shift > 0 )
+    {
+      /* upscaling too much just wastes time */
+      if ( shift > 2 )
+        shift = 2;
+
+      q1 <<=  shift;
+      q2 <<=  shift;
+      q3 <<=  shift;
+      q4 <<=  shift;
+    }
+    else
+    {
+      q1 >>= -shift;
+      q2 >>= -shift;
+      q3 >>= -shift;
+      q4 >>= -shift;
+    }
+
+    /* for a peak to exist above 0, the cubic segment must have */
+    /* at least one of its control off-points above 0.          */
+    while ( q2 > 0 || q3 > 0 )
     {
       /* determine which half contains the maximum and split */
       if ( q1 + q2 > q3 + q4 ) /* first half */
@@ -240,17 +320,22 @@
       /* check whether either end reached the maximum */
       if ( q1 == q2 && q1 >= q3 )
       {
-        max = q1;
+        peak = q1;
         break;
       }
       if ( q3 == q4 && q2 <= q4 )
       {
-        max = q4;
+        peak = q4;
         break;
       }
     }
 
-    return max;
+    if ( shift > 0 )
+      peak >>=  shift;
+    else
+      peak <<= -shift;
+
+    return peak;
   }
 
 
@@ -262,65 +347,17 @@
                     FT_Pos*  min,
                     FT_Pos*  max )
   {
-    FT_Pos  nmin, nmax;
-    FT_Int  shift;
-
-
     /* 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.                                   */
+    /* the bbox that contains all on-points.  So at least one of the     */
+    /* conditions below holds and cubic_peak is called with at least one */
+    /* non-zero argument.                                                */
 
-    shift = 27 - FT_MSB( FT_ABS( p2 ) | FT_ABS( p3 ) );
-
-    if ( shift > 0 )
-    {
-      /* 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
-    {
-      p1 >>= -shift;
-      p2 >>= -shift;
-      p3 >>= -shift;
-      p4 >>= -shift;
-      nmin = *min >> -shift;
-      nmax = *max >> -shift;
-    }
-
-    nmax =  update_cubic_max(  p1,  p2,  p3,  p4,  nmax );
+    if ( p2 > *max || p3 > *max )
+      *max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max );
 
     /* now flip the signs to update the minimum */
-    nmin = -update_cubic_max( -p1, -p2, -p3, -p4, -nmin );
-
-    if ( shift > 0 )
-    {
-      nmin >>=  shift;
-      nmax >>=  shift;
-    }
-    else
-    {
-      nmin <<= -shift;
-      nmax <<= -shift;
-    }
-
-    if ( nmin < *min )
-      *min = nmin;
-    if ( nmax > *max )
-      *max = nmax;
+    if ( p2 < *min || p3 < *min )
+      *min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 );
   }
 
 
@@ -385,22 +422,26 @@
     return 0;
   }
 
-FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
+
+  FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
     (FT_Outline_MoveTo_Func) BBox_Move_To,
-    (FT_Outline_LineTo_Func) BBox_Move_To,
+    (FT_Outline_LineTo_Func) BBox_Line_To,
     (FT_Outline_ConicTo_Func)BBox_Conic_To,
     (FT_Outline_CubicTo_Func)BBox_Cubic_To,
     0, 0
   )
 
+
   /* documentation is in ftbbox.h */
 
   FT_EXPORT_DEF( FT_Error )
   FT_Outline_Get_BBox( FT_Outline*  outline,
                        FT_BBox     *abbox )
   {
-    FT_BBox     cbox;
-    FT_BBox     bbox;
+    FT_BBox     cbox = {  0x7FFFFFFFL,  0x7FFFFFFFL,
+                         -0x7FFFFFFFL, -0x7FFFFFFFL };
+    FT_BBox     bbox = {  0x7FFFFFFFL,  0x7FFFFFFFL,
+                         -0x7FFFFFFFL, -0x7FFFFFFFL };
     FT_Vector*  vec;
     FT_UShort   n;
 
@@ -424,32 +465,13 @@
     /* coincide, we exit immediately.                             */
 
     vec = outline->points;
-    bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
-    bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
-    vec++;
 
-    for ( n = 1; n < outline->n_points; n++ )
+    for ( n = 0; n < outline->n_points; n++ )
     {
-      FT_Pos  x = vec->x;
-      FT_Pos  y = vec->y;
-
-
-      /* update control box */
-      if ( x < cbox.xMin ) cbox.xMin = x;
-      if ( x > cbox.xMax ) cbox.xMax = x;
-
-      if ( y < cbox.yMin ) cbox.yMin = y;
-      if ( y > cbox.yMax ) cbox.yMax = y;
+      FT_UPDATE_BBOX( vec, cbox);
 
       if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
-      {
-        /* update bbox for `on' points only */
-        if ( x < bbox.xMin ) bbox.xMin = x;
-        if ( x > bbox.xMax ) bbox.xMax = x;
-
-        if ( y < bbox.yMin ) bbox.yMin = y;
-        if ( y > bbox.yMax ) bbox.yMax = y;
-      }
+        FT_UPDATE_BBOX( vec, bbox);
 
       vec++;
     }
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 6542c79..24fead3 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (body).                       */
 /*                                                                         */
-/*  Copyright 2004-2009, 2011, 2013, 2014 by                               */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,9 +31,20 @@
   /* documentation is in ftbitmap.h */
 
   FT_EXPORT_DEF( void )
+  FT_Bitmap_Init( FT_Bitmap  *abitmap )
+  {
+    if ( abitmap )
+      *abitmap = null_bitmap;
+  }
+
+
+  /* deprecated function name; retained for ABI compatibility */
+
+  FT_EXPORT_DEF( void )
   FT_Bitmap_New( FT_Bitmap  *abitmap )
   {
-    *abitmap = null_bitmap;
+    if ( abitmap )
+      *abitmap = null_bitmap;
   }
 
 
@@ -44,25 +55,42 @@
                   const FT_Bitmap  *source,
                   FT_Bitmap        *target)
   {
-    FT_Memory  memory = library->memory;
+    FT_Memory  memory;
     FT_Error   error  = FT_Err_Ok;
-    FT_Int     pitch  = source->pitch;
-    FT_ULong   size;
 
+    FT_Int    pitch;
+    FT_ULong  size;
+
+    FT_Int  source_pitch_sign, target_pitch_sign;
+
+
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
+    if ( !source || !target )
+      return FT_THROW( Invalid_Argument );
 
     if ( source == target )
       return FT_Err_Ok;
 
+    source_pitch_sign = source->pitch < 0 ? -1 : 1;
+    target_pitch_sign = target->pitch < 0 ? -1 : 1;
+
     if ( source->buffer == NULL )
     {
       *target = *source;
+      if ( source_pitch_sign != target_pitch_sign )
+        target->pitch = -target->pitch;
 
       return FT_Err_Ok;
     }
 
+    memory = library->memory;
+    pitch  = source->pitch;
+
     if ( pitch < 0 )
       pitch = -pitch;
-    size = (FT_ULong)( pitch * source->rows );
+    size = (FT_ULong)pitch * source->rows;
 
     if ( target->buffer )
     {
@@ -70,9 +98,9 @@
       FT_ULong  target_size;
 
 
-      if ( target_pitch < 0  )
+      if ( target_pitch < 0 )
         target_pitch = -target_pitch;
-      target_size = (FT_ULong)( target_pitch * target->rows );
+      target_size = (FT_ULong)target_pitch * target->rows;
 
       if ( target_size != size )
         (void)FT_QREALLOC( target->buffer, target_size, size );
@@ -89,13 +117,35 @@
       *target = *source;
       target->buffer = p;
 
-      FT_MEM_COPY( target->buffer, source->buffer, size );
+      if ( source_pitch_sign == target_pitch_sign )
+        FT_MEM_COPY( target->buffer, source->buffer, size );
+      else
+      {
+        /* take care of bitmap flow */
+        FT_UInt   i;
+        FT_Byte*  s = source->buffer;
+        FT_Byte*  t = target->buffer;
+
+
+        t += (FT_ULong)pitch * ( target->rows - 1 );
+
+        for ( i = target->rows; i > 0; i-- )
+        {
+          FT_ARRAY_COPY( t, s, pitch );
+
+          s += pitch;
+          t -= pitch;
+        }
+      }
     }
 
     return error;
   }
 
 
+  /* Enlarge `bitmap' horizontally and vertically by `xpixels' */
+  /* and `ypixels', respectively.                              */
+
   static FT_Error
   ft_bitmap_assure_buffer( FT_Memory   memory,
                            FT_Bitmap*  bitmap,
@@ -106,7 +156,7 @@
     int             pitch;
     int             new_pitch;
     FT_UInt         bpp;
-    FT_Int          i, width, height;
+    FT_UInt         i, width, height;
     unsigned char*  buffer = NULL;
 
 
@@ -120,21 +170,21 @@
     {
     case FT_PIXEL_MODE_MONO:
       bpp       = 1;
-      new_pitch = ( width + xpixels + 7 ) >> 3;
+      new_pitch = (int)( ( width + xpixels + 7 ) >> 3 );
       break;
     case FT_PIXEL_MODE_GRAY2:
       bpp       = 2;
-      new_pitch = ( width + xpixels + 3 ) >> 2;
+      new_pitch = (int)( ( width + xpixels + 3 ) >> 2 );
       break;
     case FT_PIXEL_MODE_GRAY4:
       bpp       = 4;
-      new_pitch = ( width + xpixels + 1 ) >> 1;
+      new_pitch = (int)( ( width + xpixels + 1 ) >> 1 );
       break;
     case FT_PIXEL_MODE_GRAY:
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
       bpp       = 8;
-      new_pitch = ( width + xpixels );
+      new_pitch = (int)( width + xpixels );
       break;
     default:
       return FT_THROW( Invalid_Glyph_Format );
@@ -144,17 +194,17 @@
     if ( ypixels == 0 && new_pitch <= pitch )
     {
       /* zero the padding */
-      FT_Int  bit_width = pitch * 8;
-      FT_Int  bit_last  = ( width + xpixels ) * bpp;
+      FT_UInt  bit_width = (FT_UInt)pitch * 8;
+      FT_UInt  bit_last  = ( width + xpixels ) * bpp;
 
 
       if ( bit_last < bit_width )
       {
         FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
         FT_Byte*  end   = bitmap->buffer + pitch;
-        FT_Int    shift = bit_last & 7;
+        FT_UInt   shift = bit_last & 7;
         FT_UInt   mask  = 0xFF00U >> shift;
-        FT_Int    count = height;
+        FT_UInt   count = height;
 
 
         for ( ; count > 0; count--, line += pitch, end += pitch )
@@ -168,33 +218,38 @@
             write++;
           }
           if ( write < end )
-            FT_MEM_ZERO( write, end-write );
+            FT_MEM_ZERO( write, end - write );
         }
       }
 
       return FT_Err_Ok;
     }
 
+    /* otherwise allocate new buffer */
     if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
       return error;
 
+    /* new rows get added at the top of the bitmap, */
+    /* thus take care of the flow direction         */
     if ( bitmap->pitch > 0 )
     {
-      FT_Int  len = ( width * bpp + 7 ) >> 3;
+      FT_UInt  len = ( width * bpp + 7 ) >> 3;
 
 
       for ( i = 0; i < bitmap->rows; i++ )
-        FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
-                     bitmap->buffer + pitch * i, len );
+        FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ),
+                     bitmap->buffer + (FT_UInt)pitch * i,
+                     len );
     }
     else
     {
-      FT_Int  len = ( width * bpp + 7 ) >> 3;
+      FT_UInt  len = ( width * bpp + 7 ) >> 3;
 
 
       for ( i = 0; i < bitmap->rows; i++ )
-        FT_MEM_COPY( buffer + new_pitch * i,
-                     bitmap->buffer + pitch * i, len );
+        FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i,
+                     bitmap->buffer + (FT_UInt)pitch * i,
+                     len );
     }
 
     FT_FREE( bitmap->buffer );
@@ -220,7 +275,8 @@
   {
     FT_Error        error;
     unsigned char*  p;
-    FT_Int          i, x, y, pitch;
+    FT_Int          i, x, pitch;
+    FT_UInt         y;
     FT_Int          xstr, ystr;
 
 
@@ -248,17 +304,11 @@
     case FT_PIXEL_MODE_GRAY4:
       {
         FT_Bitmap  tmp;
-        FT_Int     align;
 
 
-        if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
-          align = ( bitmap->width + xstr + 3 ) / 4;
-        else
-          align = ( bitmap->width + xstr + 1 ) / 2;
-
-        FT_Bitmap_New( &tmp );
-
-        error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
+        /* convert to 8bpp */
+        FT_Bitmap_Init( &tmp );
+        error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 );
         if ( error )
           return error;
 
@@ -285,21 +335,23 @@
       return FT_Err_Ok;
     }
 
-    error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
+    error = ft_bitmap_assure_buffer( library->memory, bitmap,
+                                     (FT_UInt)xstr, (FT_UInt)ystr );
     if ( error )
       return error;
 
+    /* take care of bitmap flow */
     pitch = bitmap->pitch;
     if ( pitch > 0 )
       p = bitmap->buffer + pitch * ystr;
     else
     {
       pitch = -pitch;
-      p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
+      p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 );
     }
 
     /* for each row */
-    for ( y = 0; y < bitmap->rows ; y++ )
+    for ( y = 0; y < bitmap->rows; y++ )
     {
       /*
        * Horizontally:
@@ -309,7 +361,7 @@
        */
       for ( x = pitch - 1; x >= 0; x-- )
       {
-        unsigned char tmp;
+        unsigned char  tmp;
 
 
         tmp = p[x];
@@ -324,7 +376,7 @@
               p[x] |= p[x - 1] << ( 8 - i );
 
 #if 0
-            if ( p[x] == 0xff )
+            if ( p[x] == 0xFF )
               break;
 #endif
           }
@@ -334,12 +386,12 @@
             {
               if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
               {
-                p[x] = (unsigned char)(bitmap->num_grays - 1);
+                p[x] = (unsigned char)( bitmap->num_grays - 1 );
                 break;
               }
               else
               {
-                p[x] = (unsigned char)(p[x] + p[x-i]);
+                p[x] = (unsigned char)( p[x] + p[x - i] );
                 if ( p[x] == bitmap->num_grays - 1 )
                   break;
               }
@@ -368,8 +420,8 @@
       p += bitmap->pitch;
     }
 
-    bitmap->width += xstr;
-    bitmap->rows += ystr;
+    bitmap->width += (FT_UInt)xstr;
+    bitmap->rows += (FT_UInt)ystr;
 
     return FT_Err_Ok;
   }
@@ -378,11 +430,11 @@
   static FT_Byte
   ft_gray_for_premultiplied_srgb_bgra( const FT_Byte*  bgra )
   {
-    FT_Byte   a = bgra[3];
-    FT_ULong  l;
+    FT_UInt  a = bgra[3];
+    FT_UInt  l;
 
 
-    /* Short-circuit transparent color to avoid div-by-zero. */
+    /* Short-circuit transparent color to avoid division by zero. */
     if ( !a )
       return 0;
 
@@ -392,17 +444,17 @@
      * A gamma of 2.2 is fair to assume.  And then, we need to
      * undo the premultiplication too.
      *
-     * http://accessibility.kde.org/hsl-adjusted.php
+     *   http://accessibility.kde.org/hsl-adjusted.php
      *
      * We do the computation with integers only, applying a gamma of 2.0.
-     * The following will never overflow 32 bits; it is a scaled-up
-     * luminosity with premultiplication not yet undone. 
+     * We guarantee 32-bit arithmetic to avoid overflow but the resulting
+     * luminosity fits into 16 bits.
      *
      */
 
-    l =  4731UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
-        46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
-        13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2];
+    l = (  4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
+          46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
+          13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
 
     /*
      * Final transparency can be determined as follows.
@@ -413,11 +465,11 @@
      *
      * So the formula is a * (1 - l) = a - l * a.
      *
-     * In the actual code, we undo premultiplication and scale down again.
+     * We still need to undo premultiplication by dividing l by a*a.
      *
      */
 
-    return a - (FT_Byte)( ( l / a ) >> 16 );
+    return (FT_Byte)( a - l / a );
   }
 
 
@@ -432,10 +484,16 @@
     FT_Error   error = FT_Err_Ok;
     FT_Memory  memory;
 
+    FT_Byte*  s;
+    FT_Byte*  t;
+
 
     if ( !library )
       return FT_THROW( Invalid_Library_Handle );
 
+    if ( !source || !target )
+      return FT_THROW( Invalid_Argument );
+
     memory = library->memory;
 
     switch ( source->pixel_mode )
@@ -448,13 +506,15 @@
     case FT_PIXEL_MODE_LCD_V:
     case FT_PIXEL_MODE_BGRA:
       {
-        FT_Int   pad;
-        FT_Long  old_size;
+        FT_Int    pad, old_target_pitch, target_pitch;
+        FT_ULong  old_size;
 
 
-        old_size = target->rows * target->pitch;
-        if ( old_size < 0 )
-          old_size = -old_size;
+        old_target_pitch = target->pitch;
+        if ( old_target_pitch < 0 )
+          old_target_pitch = -old_target_pitch;
+
+        old_size = target->rows * (FT_UInt)old_target_pitch;
 
         target->pixel_mode = FT_PIXEL_MODE_GRAY;
         target->rows       = source->rows;
@@ -463,21 +523,23 @@
         pad = 0;
         if ( alignment > 0 )
         {
-          pad = source->width % alignment;
+          pad = (FT_Int)source->width % alignment;
           if ( pad != 0 )
             pad = alignment - pad;
         }
 
-        target->pitch = source->width + pad;
+        target_pitch = (FT_Int)source->width + pad;
 
-        if ( target->pitch > 0                                     &&
-             (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
+        if ( target_pitch > 0                                               &&
+             (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
           return FT_THROW( Invalid_Argument );
 
-        if ( target->rows * target->pitch > old_size             &&
+        if ( target->rows * (FT_ULong)target_pitch > old_size              &&
              FT_QREALLOC( target->buffer,
-                          old_size, target->rows * target->pitch ) )
+                          old_size, target->rows * (FT_UInt)target_pitch ) )
           return error;
+
+        target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
       }
       break;
 
@@ -485,13 +547,20 @@
       error = FT_THROW( Invalid_Argument );
     }
 
+    s = source->buffer;
+    t = target->buffer;
+
+    /* take care of bitmap flow */
+    if ( source->pitch < 0 )
+      s -= source->pitch * (FT_Int)( source->rows - 1 );
+    if ( target->pitch < 0 )
+      t -= target->pitch * (FT_Int)( target->rows - 1 );
+
     switch ( source->pixel_mode )
     {
     case FT_PIXEL_MODE_MONO:
       {
-        FT_Byte*  s = source->buffer;
-        FT_Byte*  t = target->buffer;
-        FT_Int    i;
+        FT_UInt  i;
 
 
         target->num_grays = 2;
@@ -500,7 +569,7 @@
         {
           FT_Byte*  ss = s;
           FT_Byte*  tt = t;
-          FT_Int    j;
+          FT_UInt   j;
 
 
           /* get the full bytes */
@@ -548,12 +617,8 @@
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
       {
-        FT_Int    width   = source->width;
-        FT_Byte*  s       = source->buffer;
-        FT_Byte*  t       = target->buffer;
-        FT_Int    s_pitch = source->pitch;
-        FT_Int    t_pitch = target->pitch;
-        FT_Int    i;
+        FT_UInt  width = source->width;
+        FT_UInt  i;
 
 
         target->num_grays = 256;
@@ -562,8 +627,8 @@
         {
           FT_ARRAY_COPY( t, s, width );
 
-          s += s_pitch;
-          t += t_pitch;
+          s += source->pitch;
+          t += target->pitch;
         }
       }
       break;
@@ -571,9 +636,7 @@
 
     case FT_PIXEL_MODE_GRAY2:
       {
-        FT_Byte*  s = source->buffer;
-        FT_Byte*  t = target->buffer;
-        FT_Int    i;
+        FT_UInt  i;
 
 
         target->num_grays = 4;
@@ -582,7 +645,7 @@
         {
           FT_Byte*  ss = s;
           FT_Byte*  tt = t;
-          FT_Int    j;
+          FT_UInt   j;
 
 
           /* get the full bytes */
@@ -623,9 +686,7 @@
 
     case FT_PIXEL_MODE_GRAY4:
       {
-        FT_Byte*  s = source->buffer;
-        FT_Byte*  t = target->buffer;
-        FT_Int    i;
+        FT_UInt  i;
 
 
         target->num_grays = 16;
@@ -634,7 +695,7 @@
         {
           FT_Byte*  ss = s;
           FT_Byte*  tt = t;
-          FT_Int    j;
+          FT_UInt   j;
 
 
           /* get the full bytes */
@@ -659,13 +720,10 @@
       }
       break;
 
+
     case FT_PIXEL_MODE_BGRA:
       {
-        FT_Byte*  s       = source->buffer;
-        FT_Byte*  t       = target->buffer;
-        FT_Int    s_pitch = source->pitch;
-        FT_Int    t_pitch = target->pitch;
-        FT_Int    i;
+        FT_UInt  i;
 
 
         target->num_grays = 256;
@@ -674,7 +732,7 @@
         {
           FT_Byte*  ss = s;
           FT_Byte*  tt = t;
-          FT_Int    j;
+          FT_UInt   j;
 
 
           for ( j = source->width; j > 0; j-- )
@@ -685,8 +743,8 @@
             tt += 1;
           }
 
-          s += s_pitch;
-          t += t_pitch;
+          s += source->pitch;
+          t += target->pitch;
         }
       }
       break;
@@ -711,7 +769,7 @@
       FT_Error   error;
 
 
-      FT_Bitmap_New( &bitmap );
+      FT_Bitmap_Init( &bitmap );
       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
       if ( error )
         return error;
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index 4db43e0..67549d0 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Arithmetic computations (body).                                      */
 /*                                                                         */
-/*  Copyright 1996-2006, 2008, 2012-2014 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -40,235 +40,7 @@
 #include FT_INTERNAL_OBJECTS_H
 
 
-#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
-  /* Provide assembler fragments for performance-critical functions. */
-  /* 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 */
-
-  static __inline FT_Int32
-  FT_MulFix_arm( FT_Int32  a,
-                 FT_Int32  b )
-  {
-    register FT_Int32  t, t2;
-
-
-    __asm
-    {
-      smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
-      mov   a,  t,  asr #31         /* a   = (hi >> 31) */
-      add   a,  a,  #0x8000         /* a  += 0x8000 */
-      adds  t2, t2, a               /* t2 += a */
-      adc   t,  t,  #0              /* t  += carry */
-      mov   a,  t2, lsr #16         /* a   = t2 >> 16 */
-      orr   a,  a,  t,  lsl #16     /* a  |= t << 16 */
-    }
-    return a;
-  }
-
-#endif /* __CC_ARM || __ARMCC__ */
-
-
-#ifdef __GNUC__
-
-#if defined( __arm__ )                                 && \
-    ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
-    !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
-
-#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
-
-  /* documentation is in freetype.h */
-
-  static __inline__ FT_Int32
-  FT_MulFix_arm( FT_Int32  a,
-                 FT_Int32  b )
-  {
-    register FT_Int32  t, t2;
-
-
-    __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) */
-#if defined( __clang__ ) && defined( __thumb2__ )
-      "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 */
-      "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
-      : "=r"(a), "=&r"(t2), "=&r"(t)
-      : "r"(a), "r"(b)
-      : "cc" );
-    return a;
-  }
-
-#endif /* __arm__                      && */
-       /* ( __thumb2__ || !__thumb__ ) && */
-       /* !( __CC_ARM || __ARMCC__ )      */
-
-
-#if defined( __i386__ )
-
-#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
-
-  /* documentation is in freetype.h */
-
-  static __inline__ FT_Int32
-  FT_MulFix_i386( FT_Int32  a,
-                  FT_Int32  b )
-  {
-    register FT_Int32  result;
-
-
-    __asm__ __volatile__ (
-      "imul  %%edx\n"
-      "movl  %%edx, %%ecx\n"
-      "sarl  $31, %%ecx\n"
-      "addl  $0x8000, %%ecx\n"
-      "addl  %%ecx, %%eax\n"
-      "adcl  $0, %%edx\n"
-      "shrl  $16, %%eax\n"
-      "shll  $16, %%edx\n"
-      "addl  %%edx, %%eax\n"
-      : "=a"(result), "=d"(b)
-      : "a"(a), "d"(b)
-      : "%ecx", "cc" );
-    return result;
-  }
-
-#endif /* i386 */
-
-#endif /* __GNUC__ */
-
-
-#ifdef _MSC_VER /* Visual C++ */
-
-#ifdef _M_IX86
-
-#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
-
-  /* documentation is in freetype.h */
-
-  static __inline FT_Int32
-  FT_MulFix_i386( FT_Int32  a,
-                  FT_Int32  b )
-  {
-    register FT_Int32  result;
-
-    __asm
-    {
-      mov eax, a
-      mov edx, b
-      imul edx
-      mov ecx, edx
-      sar ecx, 31
-      add ecx, 8000h
-      add eax, ecx
-      adc edx, 0
-      shr eax, 16
-      shl edx, 16
-      add eax, edx
-      mov result, eax
-    }
-    return result;
-  }
-
-#endif /* _M_IX86 */
-
-#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__ */
-
-#if defined( __GNUC__ )
-#if ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 4 ) )
-
-#if FT_SIZEOF_INT == 4
-
-#define FT_MSB_BUILTIN( x )  ( 31 - __builtin_clz( x ) )
-
-#elif FT_SIZEOF_LONG == 4
-
-#define FT_MSB_BUILTIN( x )  ( 31 - __builtin_clzl( x ) )
-
-#endif
-
-#endif
-#endif /* __GNUC__ */
-
-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
-
-
-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
 #ifdef FT_MULFIX_ASSEMBLER
-#define FT_MULFIX_INLINED  FT_MULFIX_ASSEMBLER
-#endif
-#endif
-
-#ifdef FT_MULFIX_INLINED
 #undef FT_MulFix
 #endif
 
@@ -296,6 +68,16 @@
 #define FT_COMPONENT  trace_calc
 
 
+  /* transfer sign leaving a positive number */
+#define FT_MOVE_SIGN( x, s ) \
+  FT_BEGIN_STMNT             \
+    if ( x < 0 )             \
+    {                        \
+      x = -x;                \
+      s = -s;                \
+    }                        \
+  FT_END_STMNT
+
   /* The following three functions are available regardless of whether */
   /* FT_LONG64 is defined.                                             */
 
@@ -304,8 +86,7 @@
   FT_EXPORT_DEF( FT_Fixed )
   FT_RoundFix( FT_Fixed  a )
   {
-    return ( a >= 0 ) ?   ( a + 0x8000L ) & ~0xFFFFL
-                      : -((-a + 0x8000L ) & ~0xFFFFL );
+    return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL;
   }
 
 
@@ -314,8 +95,7 @@
   FT_EXPORT_DEF( FT_Fixed )
   FT_CeilFix( FT_Fixed  a )
   {
-    return ( a >= 0 ) ?   ( a + 0xFFFFL ) & ~0xFFFFL
-                      : -((-a + 0xFFFFL ) & ~0xFFFFL );
+    return ( a + 0xFFFFL ) & ~0xFFFFL;
   }
 
 
@@ -324,54 +104,49 @@
   FT_EXPORT_DEF( FT_Fixed )
   FT_FloorFix( FT_Fixed  a )
   {
-    return ( a >= 0 ) ?   a & ~0xFFFFL
-                      : -((-a) & ~0xFFFFL );
+    return a & ~0xFFFFL;
   }
 
+#ifndef FT_MSB
 
   FT_BASE_DEF ( FT_Int )
   FT_MSB( FT_UInt32 z )
   {
-#ifdef FT_MSB_BUILTIN
+    FT_Int  shift = 0;
 
-    return FT_MSB_BUILTIN( z );
-
-#else
-
-    FT_Int shift = 0;
 
     /* determine msb bit index in `shift' */
-    if ( z >= ( 1L << 16 ) )
+    if ( z & 0xFFFF0000UL )
     {
       z     >>= 16;
       shift  += 16;
     }
-    if ( z >= ( 1L << 8 ) )
+    if ( z & 0x0000FF00UL )
     {
       z     >>= 8;
       shift  += 8;
     }
-    if ( z >= ( 1L << 4 ) )
+    if ( z & 0x000000F0UL )
     {
       z     >>= 4;
       shift  += 4;
     }
-    if ( z >= ( 1L << 2 ) )
+    if ( z & 0x0000000CUL )
     {
       z     >>= 2;
       shift  += 2;
     }
-    if ( z >= ( 1L << 1 ) )
+    if ( z & 0x00000002UL )
     {
    /* z     >>= 1; */
       shift  += 1;
     }
 
     return shift;
-
-#endif /* FT_MSB_BUILTIN */
   }
 
+#endif /* !FT_MSB */
+
 
   /* documentation is in ftcalc.h */
 
@@ -395,80 +170,77 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c )
+  FT_MulDiv( FT_Long  a_,
+             FT_Long  b_,
+             FT_Long  c_ )
   {
-    FT_Int   s;
-    FT_Long  d;
+    FT_Int     s = 1;
+    FT_UInt64  a, b, c, d;
+    FT_Long    d_;
 
 
-    s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
-    if ( c < 0 ) { c = -c; s = -s; }
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
+    FT_MOVE_SIGN( c_, s );
 
-    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
-                         : 0x7FFFFFFFL );
+    a = (FT_UInt64)a_;
+    b = (FT_UInt64)b_;
+    c = (FT_UInt64)c_;
 
-    return ( s > 0 ) ? d : -d;
+    d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
+              : 0x7FFFFFFFUL;
+
+    d_ = (FT_Long)d;
+
+    return s < 0 ? -d_ : d_;
   }
 
 
   /* documentation is in ftcalc.h */
 
   FT_BASE_DEF( FT_Long )
-  FT_MulDiv_No_Round( FT_Long  a,
-                      FT_Long  b,
-                      FT_Long  c )
+  FT_MulDiv_No_Round( FT_Long  a_,
+                      FT_Long  b_,
+                      FT_Long  c_ )
   {
-    FT_Int   s;
-    FT_Long  d;
+    FT_Int     s = 1;
+    FT_UInt64  a, b, c, d;
+    FT_Long    d_;
 
 
-    s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
-    if ( c < 0 ) { c = -c; s = -s; }
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
+    FT_MOVE_SIGN( c_, s );
 
-    d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
-                         : 0x7FFFFFFFL );
+    a = (FT_UInt64)a_;
+    b = (FT_UInt64)b_;
+    c = (FT_UInt64)c_;
 
-    return ( s > 0 ) ? d : -d;
+    d = c > 0 ? a * b / c
+              : 0x7FFFFFFFUL;
+
+    d_ = (FT_Long)d;
+
+    return s < 0 ? -d_ : d_;
   }
 
 
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_MulFix( FT_Long  a,
-             FT_Long  b )
+  FT_MulFix( FT_Long  a_,
+             FT_Long  b_ )
   {
 #ifdef FT_MULFIX_ASSEMBLER
 
-    return FT_MULFIX_ASSEMBLER( a, b );
+    return FT_MULFIX_ASSEMBLER( (FT_Int32)a_, (FT_Int32)b_ );
 
 #else
 
-    FT_Int   s = 1;
-    FT_Long  c;
+    FT_Int64  ab = (FT_Int64)a_ * (FT_Int64)b_;
 
-
-    if ( a < 0 )
-    {
-      a = -a;
-      s = -1;
-    }
-
-    if ( b < 0 )
-    {
-      b = -b;
-      s = -s;
-    }
-
-    c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
-
-    return ( s > 0 ) ? c : -c;
+    /* this requires arithmetic right shift of signed numbers */
+    return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 );
 
 #endif /* FT_MULFIX_ASSEMBLER */
   }
@@ -477,33 +249,26 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_DivFix( FT_Long  a,
-             FT_Long  b )
+  FT_DivFix( FT_Long  a_,
+             FT_Long  b_ )
   {
-    FT_Int32   s;
-    FT_UInt32  q;
+    FT_Int     s = 1;
+    FT_UInt64  a, b, q;
+    FT_Long    q_;
 
 
-    s = 1;
-    if ( a < 0 )
-    {
-      a = -a;
-      s = -1;
-    }
-    if ( b < 0 )
-    {
-      b = -b;
-      s = -s;
-    }
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
 
-    if ( b == 0 )
-      /* check for division by 0 */
-      q = 0x7FFFFFFFL;
-    else
-      /* compute result directly */
-      q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b );
+    a = (FT_UInt64)a_;
+    b = (FT_UInt64)b_;
 
-    return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
+    q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
+              : 0x7FFFFFFFUL;
+
+    q_ = (FT_Long)q;
+
+    return s < 0 ? -q_ : q_;
   }
 
 
@@ -551,25 +316,30 @@
     FT_Int     i;
 
 
-    q = 0;
-    r = hi;
-
-    if ( r >= y )
+    if ( hi >= y )
       return (FT_UInt32)0x7FFFFFFFL;
 
-    i = 32;
+    /* We shift as many bits as we can into the high register, perform     */
+    /* 32-bit division with modulo there, then work through the remaining  */
+    /* bits with long division. This optimization is especially noticeable */
+    /* for smaller dividends that barely use the high register.            */
+
+    i = 31 - FT_MSB( hi );
+    r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */
+    q = r / y;
+    r -= q * y;   /* remainder */
+
+    i = 32 - i;   /* bits remaining in low register */
     do
     {
-      r <<= 1;
       q <<= 1;
-      r  |= lo >> 31;
+      r   = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;
 
       if ( r >= y )
       {
         r -= y;
         q |= 1;
       }
-      lo <<= 1;
     } while ( --i );
 
     return q;
@@ -581,7 +351,7 @@
             FT_Int64*  y,
             FT_Int64  *z )
   {
-    register FT_UInt32  lo, hi;
+    FT_UInt32  lo, hi;
 
 
     lo = x->lo + y->lo;
@@ -592,111 +362,155 @@
   }
 
 
-  /* documentation is in freetype.h */
-
-  /* The FT_MulDiv function has been optimized thanks to ideas from      */
-  /* Graham Asher and Alexei Podtelezhnikov.  The trick is to optimize   */
-  /* a rather common case when everything fits within 32-bits.           */
+  /*  The FT_MulDiv function has been optimized thanks to ideas from     */
+  /*  Graham Asher and Alexei Podtelezhnikov.  The trick is to optimize  */
+  /*  a rather common case when everything fits within 32-bits.          */
   /*                                                                     */
-  /*  We compute 'a*b+c/2', then divide it by 'c'. (positive values)     */
+  /*  We compute 'a*b+c/2', then divide it by 'c' (all positive values). */
   /*                                                                     */
   /*  The product of two positive numbers never exceeds the square of    */
-  /*  their mean.  Therefore, we always avoid the overflow by imposing   */
+  /*  its mean values.  Therefore, we always avoid the overflow by       */
+  /*  imposing                                                           */
   /*                                                                     */
-  /*  ( a + b ) / 2 <= sqrt( X - c/2 )                                   */
+  /*    (a + b) / 2 <= sqrt(X - c/2)    ,                                */
   /*                                                                     */
-  /*  where X = 2^31 - 1.  Now we replace sqrt with a linear function    */
-  /*  that is smaller or equal in the entire range of c from 0 to X;     */
-  /*  it should be equal to sqrt(X) and sqrt(X/2) at the range termini.  */
-  /*  Substituting the linear solution and explicit numbers we get       */
+  /*  where X = 2^32 - 1, the maximum unsigned 32-bit value, and using   */
+  /*  unsigned arithmetic.  Now we replace `sqrt' with a linear function */
+  /*  that is smaller or equal for all values of c in the interval       */
+  /*  [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the       */
+  /*  endpoints.  Substituting the linear solution and explicit numbers  */
+  /*  we get                                                             */
   /*                                                                     */
-  /*  a + b <= 92681.9 - c / 79108.95                                    */
+  /*    a + b <= 131071.99 - c / 122291.84    .                          */
   /*                                                                     */
-  /*  In practice we use a faster and even stronger inequality           */
+  /*  In practice, we should use a faster and even stronger inequality   */
   /*                                                                     */
-  /*  a + b <= 92681 - (c >> 16)                                         */
+  /*    a + b <= 131071 - (c >> 16)                                      */
   /*                                                                     */
+  /*  or, alternatively,                                                 */
+  /*                                                                     */
+  /*    a + b <= 129894 - (c >> 17)    .                                 */
+  /*                                                                     */
+  /*  FT_MulFix, on the other hand, is optimized for a small value of    */
+  /*  the first argument, when the second argument can be much larger.   */
+  /*  This can be achieved by scaling the second argument and the limit  */
+  /*  in the above inequalities.  For example,                           */
+  /*                                                                     */
+  /*    a + (b >> 8) <= (131071 >> 4)                                    */
+  /*                                                                     */
+  /*  covers the practical range of use. The actual test below is a bit  */
+  /*  tighter to avoid the border case overflows.                        */
+  /*                                                                     */
+  /*  In the case of FT_DivFix, the exact overflow check                 */
+  /*                                                                     */
+  /*    a << 16 <= X - c/2                                               */
+  /*                                                                     */
+  /*  is scaled down by 2^16 and we use                                  */
+  /*                                                                     */
+  /*    a <= 65535 - (c >> 17)    .                                      */
+
+  /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c )
+  FT_MulDiv( FT_Long  a_,
+             FT_Long  b_,
+             FT_Long  c_ )
   {
-    long  s;
+    FT_Int     s = 1;
+    FT_UInt32  a, b, c;
 
 
     /* XXX: this function does not allow 64-bit arguments */
-    if ( a == 0 || b == c )
-      return a;
 
-    s  = a; a = FT_ABS( a );
-    s ^= b; b = FT_ABS( b );
-    s ^= c; c = FT_ABS( c );
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
+    FT_MOVE_SIGN( c_, s );
 
-    if ( (FT_ULong)a + (FT_ULong)b <= 92681UL - ( c >> 16 ) && c > 0 )
+    a = (FT_UInt32)a_;
+    b = (FT_UInt32)b_;
+    c = (FT_UInt32)c_;
+
+    if ( c == 0 )
+      a = 0x7FFFFFFFUL;
+
+    else if ( a + b <= 129894UL - ( c >> 17 ) )
       a = ( a * b + ( c >> 1 ) ) / c;
 
-    else if ( (FT_Int32)c > 0 )
+    else
     {
       FT_Int64  temp, temp2;
 
 
-      ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
+      ft_multo64( a, b, &temp );
 
       temp2.hi = 0;
-      temp2.lo = (FT_UInt32)(c >> 1);
-      FT_Add64( &temp, &temp2, &temp );
-      a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
-    }
-    else
-      a = 0x7FFFFFFFL;
+      temp2.lo = c >> 1;
 
-    return ( s < 0 ? -a : a );
+      FT_Add64( &temp, &temp2, &temp );
+
+      /* last attempt to ditch long division */
+      a = temp.hi == 0 ? temp.lo / c
+                       : ft_div64by32( temp.hi, temp.lo, c );
+    }
+
+    a_ = (FT_Long)a;
+
+    return s < 0 ? -a_ : a_;
   }
 
 
   FT_BASE_DEF( FT_Long )
-  FT_MulDiv_No_Round( FT_Long  a,
-                      FT_Long  b,
-                      FT_Long  c )
+  FT_MulDiv_No_Round( FT_Long  a_,
+                      FT_Long  b_,
+                      FT_Long  c_ )
   {
-    long  s;
+    FT_Int     s = 1;
+    FT_UInt32  a, b, c;
 
 
-    if ( a == 0 || b == c )
-      return a;
+    /* XXX: this function does not allow 64-bit arguments */
 
-    s  = a; a = FT_ABS( a );
-    s ^= b; b = FT_ABS( b );
-    s ^= c; c = FT_ABS( c );
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
+    FT_MOVE_SIGN( c_, s );
 
-    if ( (FT_ULong)a + (FT_ULong)b <= 92681UL && c > 0 )
+    a = (FT_UInt32)a_;
+    b = (FT_UInt32)b_;
+    c = (FT_UInt32)c_;
+
+    if ( c == 0 )
+      a = 0x7FFFFFFFUL;
+
+    else if ( a + b <= 131071UL )
       a = a * b / c;
 
-    else if ( (FT_Int32)c > 0 )
+    else
     {
       FT_Int64  temp;
 
 
-      ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
-      a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
-    }
-    else
-      a = 0x7FFFFFFFL;
+      ft_multo64( a, b, &temp );
 
-    return ( s < 0 ? -a : a );
+      /* last attempt to ditch long division */
+      a = temp.hi == 0 ? temp.lo / c
+                       : ft_div64by32( temp.hi, temp.lo, c );
+    }
+
+    a_ = (FT_Long)a;
+
+    return s < 0 ? -a_ : a_;
   }
 
 
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_MulFix( FT_Long  a,
-             FT_Long  b )
+  FT_MulFix( FT_Long  a_,
+             FT_Long  b_ )
   {
 #ifdef FT_MULFIX_ASSEMBLER
 
-    return FT_MULFIX_ASSEMBLER( a, b );
+    return FT_MULFIX_ASSEMBLER( a_, b_ );
 
 #elif 0
 
@@ -707,13 +521,10 @@
      *  the leftmost bits by copying the sign bit, it might be faster.
      */
 
-    FT_Long   sa, sb;
-    FT_ULong  ua, ub;
+    FT_Long    sa, sb;
+    FT_UInt32  a, b;
 
 
-    if ( a == 0 || b == 0x10000L )
-      return a;
-
     /*
      *  This is a clever way of converting a signed number `a' into its
      *  absolute value (stored back into `a') and its sign.  The sign is
@@ -732,57 +543,58 @@
      *  with the value 1 rather than -1.  After that, everything else goes
      *  wrong.
      */
-    sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
-    a  = ( a ^ sa ) - sa;
-    sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
-    b  = ( b ^ sb ) - sb;
+    sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) );
+    a  = ( a_ ^ sa ) - sa;
+    sb = ( b_ >> ( sizeof ( b_ ) * 8 - 1 ) );
+    b  = ( b_ ^ sb ) - sb;
 
-    ua = (FT_ULong)a;
-    ub = (FT_ULong)b;
+    a = (FT_UInt32)a_;
+    b = (FT_UInt32)b_;
 
-    if ( ua <= 2048 && ub <= 1048576L )
-      ua = ( ua * ub + 0x8000U ) >> 16;
+    if ( a + ( b >> 8 ) <= 8190UL )
+      a = ( a * b + 0x8000U ) >> 16;
     else
     {
-      FT_ULong  al = ua & 0xFFFFU;
+      FT_UInt32  al = a & 0xFFFFUL;
 
 
-      ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
-           ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
+      a = ( a >> 16 ) * b + al * ( b >> 16 ) +
+          ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
     }
 
-    sa ^= sb,
-    ua  = (FT_ULong)(( ua ^ sa ) - sa);
+    sa ^= sb;
+    a   = ( a ^ sa ) - sa;
 
-    return (FT_Long)ua;
+    return (FT_Long)a;
 
 #else /* 0 */
 
-    FT_Long   s;
-    FT_ULong  ua, ub;
+    FT_Int     s = 1;
+    FT_UInt32  a, b;
 
 
-    if ( a == 0 || b == 0x10000L )
-      return a;
+    /* XXX: this function does not allow 64-bit arguments */
 
-    s  = a; a = FT_ABS( a );
-    s ^= b; b = FT_ABS( b );
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
 
-    ua = (FT_ULong)a;
-    ub = (FT_ULong)b;
+    a = (FT_UInt32)a_;
+    b = (FT_UInt32)b_;
 
-    if ( ua <= 2048 && ub <= 1048576L )
-      ua = ( ua * ub + 0x8000UL ) >> 16;
+    if ( a + ( b >> 8 ) <= 8190UL )
+      a = ( a * b + 0x8000UL ) >> 16;
     else
     {
-      FT_ULong  al = ua & 0xFFFFUL;
+      FT_UInt32  al = a & 0xFFFFUL;
 
 
-      ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
-           ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
+      a = ( a >> 16 ) * b + al * ( b >> 16 ) +
+          ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
     }
 
-    return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
+    a_ = (FT_Long)a;
+
+    return s < 0 ? -a_ : a_;
 
 #endif /* 0 */
 
@@ -792,26 +604,31 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Long )
-  FT_DivFix( FT_Long  a,
-             FT_Long  b )
+  FT_DivFix( FT_Long  a_,
+             FT_Long  b_ )
   {
-    FT_Int32   s;
-    FT_UInt32  q;
+    FT_Int     s = 1;
+    FT_UInt32  a, b, q;
+    FT_Long    q_;
 
 
     /* XXX: this function does not allow 64-bit arguments */
-    s  = (FT_Int32)a; a = FT_ABS( a );
-    s ^= (FT_Int32)b; b = FT_ABS( b );
 
-    if ( (FT_UInt32)b == 0 )
+    FT_MOVE_SIGN( a_, s );
+    FT_MOVE_SIGN( b_, s );
+
+    a = (FT_UInt32)a_;
+    b = (FT_UInt32)b_;
+
+    if ( b == 0 )
     {
       /* check for division by 0 */
-      q = (FT_UInt32)0x7FFFFFFFL;
+      q = 0x7FFFFFFFUL;
     }
-    else if ( ( a >> 16 ) == 0 )
+    else if ( a <= 65535UL - ( b >> 17 ) )
     {
       /* compute result directly */
-      q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
+      q = ( ( a << 16 ) + ( b >> 1 ) ) / b;
     }
     else
     {
@@ -819,140 +636,22 @@
       FT_Int64  temp, temp2;
 
 
-      temp.hi  = (FT_Int32)( a >> 16 );
-      temp.lo  = (FT_UInt32)a << 16;
+      temp.hi  = a >> 16;
+      temp.lo  = a << 16;
       temp2.hi = 0;
-      temp2.lo = (FT_UInt32)( b >> 1 );
+      temp2.lo = b >> 1;
+
       FT_Add64( &temp, &temp2, &temp );
-      q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );
+      q = ft_div64by32( temp.hi, temp.lo, b );
     }
 
-    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+    q_ = (FT_Long)q;
+
+    return s < 0 ? -q_ : q_;
   }
 
 
-#if 0
-
-  /* documentation is in ftcalc.h */
-
-  FT_EXPORT_DEF( void )
-  FT_MulTo64( FT_Int32   x,
-              FT_Int32   y,
-              FT_Int64  *z )
-  {
-    FT_Int32  s;
-
-
-    s  = x; x = FT_ABS( x );
-    s ^= y; y = FT_ABS( y );
-
-    ft_multo64( x, y, z );
-
-    if ( s < 0 )
-    {
-      z->lo = (FT_UInt32)-(FT_Int32)z->lo;
-      z->hi = ~z->hi + !( z->lo );
-    }
-  }
-
-
-  /* apparently, the second version of this code is not compiled correctly */
-  /* on Mac machines with the MPW C compiler..  tsk, tsk, tsk...           */
-
-#if 1
-
-  FT_EXPORT_DEF( FT_Int32 )
-  FT_Div64by32( FT_Int64*  x,
-                FT_Int32   y )
-  {
-    FT_Int32   s;
-    FT_UInt32  q, r, i, lo;
-
-
-    s  = x->hi;
-    if ( s < 0 )
-    {
-      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
-      x->hi = ~x->hi + !x->lo;
-    }
-    s ^= y;  y = FT_ABS( y );
-
-    /* Shortcut */
-    if ( x->hi == 0 )
-    {
-      if ( y > 0 )
-        q = x->lo / y;
-      else
-        q = 0x7FFFFFFFL;
-
-      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
-    }
-
-    r  = x->hi;
-    lo = x->lo;
-
-    if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
-      return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
-                             /* Return Max/Min Int32 if division overflow. */
-                             /* This includes division by zero!            */
-    q = 0;
-    for ( i = 0; i < 32; i++ )
-    {
-      r <<= 1;
-      q <<= 1;
-      r  |= lo >> 31;
-
-      if ( r >= (FT_UInt32)y )
-      {
-        r -= y;
-        q |= 1;
-      }
-      lo <<= 1;
-    }
-
-    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
-  }
-
-#else /* 0 */
-
-  FT_EXPORT_DEF( FT_Int32 )
-  FT_Div64by32( FT_Int64*  x,
-                FT_Int32   y )
-  {
-    FT_Int32   s;
-    FT_UInt32  q;
-
-
-    s  = x->hi;
-    if ( s < 0 )
-    {
-      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
-      x->hi = ~x->hi + !x->lo;
-    }
-    s ^= y;  y = FT_ABS( y );
-
-    /* Shortcut */
-    if ( x->hi == 0 )
-    {
-      if ( y > 0 )
-        q = ( x->lo + ( y >> 1 ) ) / y;
-      else
-        q = 0x7FFFFFFFL;
-
-      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
-    }
-
-    q = ft_div64by32( x->hi, x->lo, y );
-
-    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
-  }
-
-#endif /* 0 */
-
-#endif /* 0 */
-
-
-#endif /* FT_LONG64 */
+#endif /* !FT_LONG64 */
 
 
   /* documentation is in ftglyph.h */
@@ -1059,6 +758,102 @@
   }
 
 
+  /* documentation is in ftcalc.h */
+
+  FT_BASE_DEF( FT_UInt32 )
+  FT_Vector_NormLen( FT_Vector*  vector )
+  {
+    FT_Int32   x_ = vector->x;
+    FT_Int32   y_ = vector->y;
+    FT_Int32   b, z;
+    FT_UInt32  x, y, u, v, l;
+    FT_Int     sx = 1, sy = 1, shift;
+
+
+    FT_MOVE_SIGN( x_, sx );
+    FT_MOVE_SIGN( y_, sy );
+
+    x = (FT_UInt32)x_;
+    y = (FT_UInt32)y_;
+
+    /* trivial cases */
+    if ( x == 0 )
+    {
+      if ( y > 0 )
+        vector->y = sy * 0x10000;
+      return y;
+    }
+    else if ( y == 0 )
+    {
+      if ( x > 0 )
+        vector->x = sx * 0x10000;
+      return x;
+    }
+
+    /* Estimate length and prenormalize by shifting so that */
+    /* the new approximate length is between 2/3 and 4/3.   */
+    /* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps  */
+    /* achieve this in 16.16 fixed-point representation.    */
+    l = x > y ? x + ( y >> 1 )
+              : y + ( x >> 1 );
+
+    shift  = 31 - FT_MSB( l );
+    shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );
+
+    if ( shift > 0 )
+    {
+      x <<= shift;
+      y <<= shift;
+
+      /* re-estimate length for tiny vectors */
+      l = x > y ? x + ( y >> 1 )
+                : y + ( x >> 1 );
+    }
+    else
+    {
+      x >>= -shift;
+      y >>= -shift;
+      l >>= -shift;
+    }
+
+    /* lower linear approximation for reciprocal length minus one */
+    b = 0x10000 - (FT_Int32)l;
+
+    x_ = (FT_Int32)x;
+    y_ = (FT_Int32)y;
+
+    /* Newton's iterations */
+    do
+    {
+      u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
+      v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );
+
+      /* Normalized squared length in the parentheses approaches 2^32. */
+      /* On two's complement systems, converting to signed gives the   */
+      /* difference with 2^32 even if the expression wraps around.     */
+      z = -(FT_Int32)( u * u + v * v ) / 0x200;
+      z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;
+
+      b += z;
+
+    } while ( z > 0 );
+
+    vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
+    vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;
+
+    /* Conversion to signed helps to recover from likely wrap around */
+    /* in calculating the prenormalized length, because it gives the */
+    /* correct difference with 2^32 on two's complement systems.     */
+    l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
+    if ( shift > 0 )
+      l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
+    else
+      l <<= -shift;
+
+    return l;
+  }
+
+
 #if 0
 
   /* documentation is in ftcalc.h */
@@ -1075,7 +870,7 @@
     if ( x > 0 )
     {
       rem_hi = 0;
-      rem_lo = x;
+      rem_lo = (FT_UInt32)x;
       count  = 24;
       do
       {
@@ -1106,58 +901,40 @@
                          FT_Pos  out_x,
                          FT_Pos  out_y )
   {
-    FT_Long  result; /* avoid overflow on 16-bit system */
-
-
-    /* deal with the trivial cases quickly */
-    if ( in_y == 0 )
-    {
-      if ( in_x >= 0 )
-        result = out_y;
-      else
-        result = -out_y;
-    }
-    else if ( in_x == 0 )
-    {
-      if ( in_y >= 0 )
-        result = -out_x;
-      else
-        result = out_x;
-    }
-    else if ( out_y == 0 )
-    {
-      if ( out_x >= 0 )
-        result = in_y;
-      else
-        result = -in_y;
-    }
-    else if ( out_x == 0 )
-    {
-      if ( out_y >= 0 )
-        result = -in_x;
-      else
-        result =  in_x;
-    }
-    else /* general case */
-    {
 #ifdef FT_LONG64
 
-      FT_Int64  delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
+    FT_Int64  delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
 
 
-      if ( delta == 0 )
-        result = 0;
-      else
-        result = 1 - 2 * ( delta < 0 );
+    return ( delta > 0 ) - ( delta < 0 );
 
 #else
 
+    FT_Int  result;
+
+
+    if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 131071UL &&
+         (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 131071UL )
+    {
+      FT_Long  z1 = in_x * out_y;
+      FT_Long  z2 = in_y * out_x;
+
+
+      if ( z1 > z2 )
+        result = +1;
+      else if ( z1 < z2 )
+        result = -1;
+      else
+        result = 0;
+    }
+    else /* products might overflow 32 bits */
+    {
       FT_Int64  z1, z2;
 
 
       /* XXX: this function does not allow 64-bit arguments */
-      ft_multo64( (FT_Int32)in_x, (FT_Int32)out_y, &z1 );
-      ft_multo64( (FT_Int32)in_y, (FT_Int32)out_x, &z2 );
+      ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 );
+      ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 );
 
       if ( z1.hi > z2.hi )
         result = +1;
@@ -1169,12 +946,12 @@
         result = -1;
       else
         result = 0;
-
-#endif
     }
 
     /* XXX: only the sign of return value, +1/0/-1 must be used */
-    return (FT_Int)result;
+    return result;
+
+#endif
   }
 
 
@@ -1186,55 +963,40 @@
                      FT_Pos  out_x,
                      FT_Pos  out_y )
   {
-    FT_Pos  ax = in_x;
-    FT_Pos  ay = in_y;
+    FT_Pos  ax = in_x + out_x;
+    FT_Pos  ay = in_y + out_y;
 
-    FT_Pos  d_in, d_out, d_corner;
+    FT_Pos  d_in, d_out, d_hypot;
 
 
-    /* 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                                         */
-    /*                                                            */
+    /* The idea of this function is to compare the length of the */
+    /* hypotenuse with the `in' and `out' length.  The `corner'  */
+    /* represented by `in' and `out' is flat if the hypotenuse's */
+    /* length isn't too large.                                   */
+    /*                                                           */
+    /* This approach has the advantage that the angle between    */
+    /* `in' and `out' is not checked.  In case one of the two    */
+    /* vectors is `dominant', this is, much larger than the      */
+    /* other vector, we thus always have a flat corner.          */
+    /*                                                           */
+    /*                hypotenuse                                 */
+    /*       x---------------------------x                       */
+    /*        \                      /                           */
+    /*         \                /                                */
+    /*      in  \          /  out                                */
+    /*           \    /                                          */
+    /*            o                                              */
+    /*              Point                                        */
 
-    if ( ax < 0 )
-      ax = -ax;
-    if ( ay < 0 )
-      ay = -ay;
-    d_in = ax + ay;  /* d_in = || in || */
-
-    ax = out_x;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = out_y;
-    if ( ay < 0 )
-      ay = -ay;
-    d_out = ax + ay;  /* d_out = || out || */
-
-    ax = out_x + in_x;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = out_y + in_y;
-    if ( ay < 0 )
-      ay = -ay;
-    d_corner = ax + ay;  /* d_corner = || in + out || */
+    d_in    = FT_HYPOT(  in_x,  in_y );
+    d_out   = FT_HYPOT( out_x, out_y );
+    d_hypot = FT_HYPOT(    ax,    ay );
 
     /* now do a simple length comparison: */
     /*                                    */
-    /*   d_in + d_out < 17/16 d_corner    */
+    /*   d_in + d_out < 17/16 d_hypot     */
 
-    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
+    return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 );
   }
 
 
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 6fb86fe..38d1a80 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Memory debugger (body).                                              */
 /*                                                                         */
-/*  Copyright 2001-2006, 2009, 2013 by                                     */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -35,7 +35,7 @@
 
 #include FT_CONFIG_STANDARD_LIBRARY_H
 
-  FT_BASE_DEF( const char* )  _ft_debug_file   = 0;
+  FT_BASE_DEF( const char* )  _ft_debug_file   = NULL;
   FT_BASE_DEF( long )         _ft_debug_lineno = 0;
 
   extern void
@@ -47,7 +47,7 @@
   typedef struct FT_MemTableRec_*   FT_MemTable;
 
 
-#define FT_MEM_VAL( addr )  ((FT_PtrDist)(FT_Pointer)( addr ))
+#define FT_MEM_VAL( addr )  ( (FT_PtrDist)(FT_Pointer)( addr ) )
 
   /*
    *  This structure holds statistics for a single allocation/release
@@ -76,7 +76,7 @@
 
 
   /*
-   *  We don't need a resizable array for the memory sources, because
+   *  We don't need a resizable array for the memory sources because
    *  their number is pretty limited within FreeType.
    */
 #define FT_MEM_SOURCE_BUCKETS  128
@@ -85,8 +85,8 @@
    *  This structure holds information related to a single allocated
    *  memory block.  If KEEPALIVE is defined, blocks that are freed by
    *  FreeType are never released to the system.  Instead, their `size'
-   *  field is set to -size.  This is mainly useful to detect double frees,
-   *  at the price of large memory footprint during execution.
+   *  field is set to `-size'.  This is mainly useful to detect double
+   *  frees, at the price of a large memory footprint during execution.
    */
   typedef struct  FT_MemNodeRec_
   {
@@ -111,20 +111,20 @@
    */
   typedef struct  FT_MemTableRec_
   {
-    FT_ULong         size;
-    FT_ULong         nodes;
+    FT_Long          size;
+    FT_Long          nodes;
     FT_MemNode*      buckets;
 
-    FT_ULong         alloc_total;
-    FT_ULong         alloc_current;
-    FT_ULong         alloc_max;
-    FT_ULong         alloc_count;
+    FT_Long          alloc_total;
+    FT_Long          alloc_current;
+    FT_Long          alloc_max;
+    FT_Long          alloc_count;
 
     FT_Bool          bound_total;
-    FT_ULong         alloc_total_max;
+    FT_Long          alloc_total_max;
 
     FT_Bool          bound_count;
-    FT_ULong         alloc_count_max;
+    FT_Long          alloc_count_max;
 
     FT_MemSource     sources[FT_MEM_SOURCE_BUCKETS];
 
@@ -142,14 +142,14 @@
 #define FT_MEM_SIZE_MIN  7
 #define FT_MEM_SIZE_MAX  13845163
 
-#define FT_FILENAME( x )  ((x) ? (x) : "unknown file")
+#define FT_FILENAME( x )  ( (x) ? (x) : "unknown file" )
 
 
   /*
    *  Prime numbers are ugly to handle.  It would be better to implement
    *  L-Hashing, which is 10% faster and doesn't require divisions.
    */
-  static const FT_UInt  ft_mem_primes[] =
+  static const FT_Int  ft_mem_primes[] =
   {
     7,
     11,
@@ -189,10 +189,10 @@
   };
 
 
-  static FT_ULong
-  ft_mem_closest_prime( FT_ULong  num )
+  static FT_Long
+  ft_mem_closest_prime( FT_Long  num )
   {
-    FT_UInt  i;
+    size_t  i;
 
 
     for ( i = 0;
@@ -204,7 +204,7 @@
   }
 
 
-  extern void
+  static void
   ft_mem_debug_panic( const char*  fmt,
                       ... )
   {
@@ -254,19 +254,20 @@
   static void
   ft_mem_table_resize( FT_MemTable  table )
   {
-    FT_ULong  new_size;
+    FT_Long  new_size;
 
 
     new_size = ft_mem_closest_prime( table->nodes );
     if ( new_size != table->size )
     {
       FT_MemNode*  new_buckets;
-      FT_ULong     i;
+      FT_Long      i;
 
 
       new_buckets = (FT_MemNode *)
-                      ft_mem_table_alloc( table,
-                                          new_size * sizeof ( FT_MemNode ) );
+                      ft_mem_table_alloc(
+                        table,
+                        new_size * (FT_Long)sizeof ( FT_MemNode ) );
       if ( new_buckets == NULL )
         return;
 
@@ -282,7 +283,7 @@
         while ( node )
         {
           next  = node->link;
-          hash  = FT_MEM_VAL( node->address ) % new_size;
+          hash  = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size;
           pnode = new_buckets + hash;
 
           node->link = pnode[0];
@@ -325,8 +326,9 @@
     table->free    = memory->free;
 
     table->buckets = (FT_MemNode *)
-                       memory->alloc( memory,
-                                      table->size * sizeof ( FT_MemNode ) );
+                       memory->alloc(
+                         memory,
+                         table->size * (FT_Long)sizeof ( FT_MemNode ) );
     if ( table->buckets )
       FT_ARRAY_ZERO( table->buckets, table->size );
     else
@@ -343,9 +345,9 @@
   static void
   ft_mem_table_destroy( FT_MemTable  table )
   {
-    FT_ULong  i;
-    FT_Long   leak_count = 0;
-    FT_ULong  leaks      = 0;
+    FT_Long  i;
+    FT_Long  leak_count = 0;
+    FT_Long  leaks      = 0;
 
 
     FT_DumpMemory( table->memory );
@@ -359,13 +361,14 @@
       while ( node )
       {
         next       = node->link;
-        node->link = 0;
+        node->link = NULL;
 
         if ( node->size > 0 )
         {
           printf(
             "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
-            node->address, node->size,
+            (void*)node->address,
+            node->size,
             FT_FILENAME( node->source->file_name ),
             node->source->line_no );
 
@@ -381,7 +384,7 @@
         ft_mem_table_free( table, node );
         node = next;
       }
-      table->buckets[i] = 0;
+      table->buckets[i] = NULL;
     }
 
     ft_mem_table_free( table, table->buckets );
@@ -430,7 +433,7 @@
 
 
     hash  = FT_MEM_VAL( address );
-    pnode = table->buckets + ( hash % table->size );
+    pnode = table->buckets + ( hash % (FT_PtrDist)table->size );
 
     for (;;)
     {
@@ -460,14 +463,14 @@
               (FT_UInt32)( 5 * _ft_debug_lineno );
     pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
 
-    for ( ;; )
+    for (;;)
     {
       node = *pnode;
       if ( node == NULL )
         break;
 
-      if ( node->file_name == _ft_debug_file &&
-           node->line_no   == _ft_debug_lineno   )
+      if ( node->file_name == _ft_debug_file   &&
+           node->line_no   == _ft_debug_lineno )
         goto Exit;
 
       pnode = &node->link;
@@ -485,11 +488,11 @@
     node->max_blocks = 0;
     node->all_blocks = 0;
 
-    node->cur_size   = 0;
-    node->max_size   = 0;
-    node->all_size   = 0;
+    node->cur_size = 0;
+    node->max_size = 0;
+    node->all_size = 0;
 
-    node->cur_max    = 0;
+    node->cur_max = 0;
 
     node->link = NULL;
     node->hash = hash;
@@ -503,7 +506,7 @@
   static void
   ft_mem_table_set( FT_MemTable  table,
                     FT_Byte*     address,
-                    FT_ULong     size,
+                    FT_Long      size,
                     FT_Long      delta )
   {
     FT_MemNode  *pnode, node;
@@ -558,7 +561,7 @@
           source->max_blocks = source->cur_blocks;
       }
 
-      if ( size > (FT_ULong)source->cur_max )
+      if ( size > source->cur_max )
         source->cur_max = size;
 
       if ( delta != 0 )
@@ -671,7 +674,7 @@
   }
 
 
-  extern FT_Pointer
+  static FT_Pointer
   ft_mem_debug_alloc( FT_Memory  memory,
                       FT_Long    size )
   {
@@ -688,14 +691,14 @@
       return NULL;
 
     /* return NULL if this allocation would overflow the maximum heap size */
-    if ( table->bound_total                                             &&
-         table->alloc_total_max - table->alloc_current > (FT_ULong)size )
+    if ( table->bound_total                                   &&
+         table->alloc_total_max - table->alloc_current > size )
       return NULL;
 
     block = (FT_Byte *)ft_mem_table_alloc( table, size );
     if ( block )
     {
-      ft_mem_table_set( table, block, (FT_ULong)size, 0 );
+      ft_mem_table_set( table, block, size, 0 );
 
       table->alloc_count++;
     }
@@ -707,7 +710,7 @@
   }
 
 
-  extern void
+  static void
   ft_mem_debug_free( FT_Memory   memory,
                      FT_Pointer  block )
   {
@@ -731,7 +734,7 @@
   }
 
 
-  extern FT_Pointer
+  static FT_Pointer
   ft_mem_debug_realloc( FT_Memory   memory,
                         FT_Long     cur_size,
                         FT_Long     new_size,
@@ -787,21 +790,22 @@
          table->alloc_count >= table->alloc_count_max )
       return NULL;
 
-    delta = (FT_Long)( new_size - cur_size );
+    delta = new_size - cur_size;
 
     /* return NULL if this allocation would overflow the maximum heap size */
-    if ( delta > 0                                                       &&
-         table->bound_total                                              &&
-         table->alloc_current + (FT_ULong)delta > table->alloc_total_max )
+    if ( delta > 0                                             &&
+         table->bound_total                                    &&
+         table->alloc_current + delta > table->alloc_total_max )
       return NULL;
 
-    new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );
+    new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
     if ( new_block == NULL )
       return NULL;
 
     ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
 
-    ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );
+    ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
+                                                     : (size_t)new_size );
 
     ft_mem_table_remove( table, (FT_Byte*)block, delta );
 
@@ -838,33 +842,33 @@
         p = getenv( "FT2_ALLOC_TOTAL_MAX" );
         if ( p != NULL )
         {
-          FT_Long   total_max = ft_atol( p );
+          FT_Long  total_max = ft_strtol( p, NULL, 10 );
 
 
           if ( total_max > 0 )
           {
             table->bound_total     = 1;
-            table->alloc_total_max = (FT_ULong)total_max;
+            table->alloc_total_max = total_max;
           }
         }
 
         p = getenv( "FT2_ALLOC_COUNT_MAX" );
         if ( p != NULL )
         {
-          FT_Long  total_count = ft_atol( p );
+          FT_Long  total_count = ft_strtol( p, NULL, 10 );
 
 
           if ( total_count > 0 )
           {
             table->bound_count     = 1;
-            table->alloc_count_max = (FT_ULong)total_count;
+            table->alloc_count_max = total_count;
           }
         }
 
         p = getenv( "FT2_KEEP_ALIVE" );
         if ( p != NULL )
         {
-          FT_Long  keep_alive = ft_atol( p );
+          FT_Long  keep_alive = ft_strtol( p, NULL, 10 );
 
 
           if ( keep_alive > 0 )
@@ -896,7 +900,6 @@
   }
 
 
-
   static int
   ft_mem_source_compare( const void*  p1,
                          const void*  p2 )
@@ -925,7 +928,7 @@
       FT_MemSource*  bucket = table->sources;
       FT_MemSource*  limit  = bucket + FT_MEM_SOURCE_BUCKETS;
       FT_MemSource*  sources;
-      FT_UInt        nn, count;
+      FT_Int         nn, count;
       const char*    fmt;
 
 
@@ -939,8 +942,9 @@
           count++;
       }
 
-      sources = (FT_MemSource*)ft_mem_table_alloc(
-                                 table, sizeof ( *sources ) * count );
+      sources = (FT_MemSource*)
+                  ft_mem_table_alloc(
+                    table, count * (FT_Long)sizeof ( *sources ) );
 
       count = 0;
       for ( bucket = table->sources; bucket < limit; bucket++ )
@@ -952,7 +956,10 @@
           sources[count++] = source;
       }
 
-      ft_qsort( sources, count, sizeof ( *sources ), ft_mem_source_compare );
+      ft_qsort( sources,
+                (size_t)count,
+                sizeof ( *sources ),
+                ft_mem_source_compare );
 
       printf( "FreeType Memory Dump: "
               "current=%ld max=%ld total=%ld count=%ld\n",
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index 39ac6ad..40925d1 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2008, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -152,8 +152,8 @@
   /* the memory and stream components which are set to 7 and 5,            */
   /* respectively.                                                         */
   /*                                                                       */
-  /* See the file <include/internal/fttrace.h> for details of the          */
-  /* available toggle names.                                               */
+  /* See the file `include/freetype/internal/fttrace.h' for details of     */
+  /* the available toggle names.                                           */
   /*                                                                       */
   /* The level must be between 0 and 7; 0 means quiet (except for serious  */
   /* runtime errors), and 7 means _very_ verbose.                          */
diff --git a/src/base/ftxf86.c b/src/base/ftfntfmt.c
similarity index 67%
rename from src/base/ftxf86.c
rename to src/base/ftfntfmt.c
index a4bf767..c6eb319 100644
--- a/src/base/ftxf86.c
+++ b/src/base/ftfntfmt.c
@@ -1,10 +1,10 @@
 /***************************************************************************/
 /*                                                                         */
-/*  ftxf86.c                                                               */
+/*  ftfntfmt.c                                                             */
 /*                                                                         */
-/*    FreeType utility file for X11 support (body).                        */
+/*    FreeType utility file for font formats (body).                       */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004 by                                          */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,12 +17,27 @@
 
 
 #include <ft2build.h>
-#include FT_XFREE86_H
+#include FT_FONT_FORMATS_H
 #include FT_INTERNAL_OBJECTS_H
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
 
 
-  /* documentation is in ftxf86.h */
+  /* documentation is in ftfntfmt.h */
+
+  FT_EXPORT_DEF( const char* )
+  FT_Get_Font_Format( FT_Face  face )
+  {
+    const char*  result = NULL;
+
+
+    if ( face )
+      FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
+
+    return result;
+  }
+
+
+  /* deprecated function name; retained for ABI compatibility */
 
   FT_EXPORT_DEF( const char* )
   FT_Get_X11_Font_Format( FT_Face  face )
@@ -31,7 +46,7 @@
 
 
     if ( face )
-      FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
+      FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
 
     return result;
   }
diff --git a/src/base/ftfstype.c b/src/base/ftfstype.c
index 0bf29c7..ae56c8f 100644
--- a/src/base/ftfstype.c
+++ b/src/base/ftfstype.c
@@ -1,62 +1,62 @@
-/***************************************************************************/

-/*                                                                         */

-/*  ftfstype.c                                                             */

-/*                                                                         */

-/*    FreeType utility file to access FSType data (body).                  */

-/*                                                                         */

-/*  Copyright 2008, 2009 by                                                */

-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */

-/*                                                                         */

-/*  This file is part of the FreeType project, and may only be used,       */

-/*  modified, and distributed under the terms of the FreeType project      */

-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */

-/*  this file you indicate that you have read the license and              */

-/*  understand and accept it fully.                                        */

-/*                                                                         */

-/***************************************************************************/

-

-#include <ft2build.h>

-#include FT_TYPE1_TABLES_H

-#include FT_TRUETYPE_TABLES_H

-#include FT_INTERNAL_SERVICE_H

-#include FT_SERVICE_POSTSCRIPT_INFO_H

-

-

-  /* documentation is in freetype.h */

-

-  FT_EXPORT_DEF( FT_UShort )

-  FT_Get_FSType_Flags( FT_Face  face )

-  {

-    TT_OS2*  os2;

-

-

-    /* first, try to get the fs_type directly from the font */

-    if ( face )

-    {

-      FT_Service_PsInfo  service = NULL;

-

-

-      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );

-

-      if ( service && service->ps_get_font_extra )

-      {

-        PS_FontExtraRec  extra;

-

-

-        if ( !service->ps_get_font_extra( face, &extra ) &&

-             extra.fs_type != 0                          )

-          return extra.fs_type;

-      }

-    }

-

-    /* look at FSType before fsType for Type42 */

-

-    if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, ft_sfnt_os2 ) ) != NULL &&

-         os2->version != 0xFFFFU                                           )

-      return os2->fsType;

-

-    return 0;

-  }

-

-

-/* END */

+/***************************************************************************/
+/*                                                                         */
+/*  ftfstype.c                                                             */
+/*                                                                         */
+/*    FreeType utility file to access FSType data (body).                  */
+/*                                                                         */
+/*  Copyright 2008-2016 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_TYPE1_TABLES_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_UShort )
+  FT_Get_FSType_Flags( FT_Face  face )
+  {
+    TT_OS2*  os2;
+
+
+    /* first, try to get the fs_type directly from the font */
+    if ( face )
+    {
+      FT_Service_PsInfo  service = NULL;
+
+
+      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+      if ( service && service->ps_get_font_extra )
+      {
+        PS_FontExtraRec  extra;
+
+
+        if ( !service->ps_get_font_extra( face, &extra ) &&
+             extra.fs_type != 0                          )
+          return extra.fs_type;
+      }
+    }
+
+    /* look at FSType before fsType for Type42 */
+
+    if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, FT_SFNT_OS2 ) ) != NULL &&
+         os2->version != 0xFFFFU                                           )
+      return os2->fsType;
+
+    return 0;
+  }
+
+
+/* END */
diff --git a/src/base/ftgasp.c b/src/base/ftgasp.c
index 8485d29..e38e55b 100644
--- a/src/base/ftgasp.c
+++ b/src/base/ftgasp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Access of TrueType's `gasp' table (body).                            */
 /*                                                                         */
-/*  Copyright 2007 by                                                      */
+/*  Copyright 2007-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c
index 3cc5c7a..c4f0ff7 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph loader (body).                                    */
 /*                                                                         */
-/*  Copyright 2002-2006, 2010, 2013 by                                     */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -212,7 +212,8 @@
 
 
     /* check points & tags */
-    new_max = base->n_points + current->n_points + n_points;
+    new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
+              n_points;
     old_max = loader->max_points;
 
     if ( new_max > old_max )
@@ -245,7 +246,7 @@
 
     /* check contours */
     old_max = loader->max_contours;
-    new_max = base->n_contours + current->n_contours +
+    new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours +
               n_contours;
     if ( new_max > old_max )
     {
@@ -329,9 +330,9 @@
     FT_GlyphLoad  base;
     FT_GlyphLoad  current;
 
-    FT_UInt       n_curr_contours;
-    FT_UInt       n_base_points;
-    FT_UInt       n;
+    FT_Int        n_curr_contours;
+    FT_Int        n_base_points;
+    FT_Int        n;
 
 
     if ( !loader )
@@ -365,8 +366,8 @@
                              FT_GlyphLoader  source )
   {
     FT_Error  error;
-    FT_UInt   num_points   = source->base.outline.n_points;
-    FT_UInt   num_contours = source->base.outline.n_contours;
+    FT_UInt   num_points   = (FT_UInt)source->base.outline.n_points;
+    FT_UInt   num_contours = (FT_UInt)source->base.outline.n_contours;
 
 
     error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index c62b3db..c2376dd 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (body).              */
 /*                                                                         */
-/*  Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -82,7 +82,7 @@
     }
     else
     {
-      FT_Bitmap_New( &glyph->bitmap );
+      FT_Bitmap_Init( &glyph->bitmap );
       error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
     }
 
@@ -125,10 +125,10 @@
     FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
 
 
-    cbox->xMin = glyph->left << 6;
-    cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
-    cbox->yMax = glyph->top << 6;
-    cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
+    cbox->xMin = glyph->left * 64;
+    cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
+    cbox->yMax = glyph->top * 64;
+    cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
   }
 
 
@@ -173,7 +173,9 @@
     }
 
     /* allocate new outline */
-    error = FT_Outline_New( library, source->n_points, source->n_contours,
+    error = FT_Outline_New( library,
+                            (FT_UInt)source->n_points,
+                            source->n_contours,
                             &glyph->outline );
     if ( error )
       goto Exit;
@@ -205,8 +207,10 @@
     FT_Library       library = FT_GLYPH( source )->library;
 
 
-    error = FT_Outline_New( library, source->outline.n_points,
-                            source->outline.n_contours, &target->outline );
+    error = FT_Outline_New( library,
+                            (FT_UInt)source->outline.n_points,
+                            source->outline.n_contours,
+                            &target->outline );
     if ( !error )
       FT_Outline_Copy( &source->outline, &target->outline );
 
@@ -287,7 +291,7 @@
      FT_Glyph   glyph  = NULL;
 
 
-     *aglyph = 0;
+     *aglyph = NULL;
 
      if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
      {
@@ -314,13 +318,13 @@
 
 
     /* check arguments */
-    if ( !target )
+    if ( !target || !source || !source->clazz )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
-    *target = 0;
+    *target = NULL;
 
     if ( !source || !source->clazz )
     {
@@ -359,7 +363,7 @@
     FT_Error    error;
     FT_Glyph    glyph;
 
-    const FT_Glyph_Class*  clazz = 0;
+    const FT_Glyph_Class*  clazz = NULL;
 
 
     if ( !slot )
@@ -399,9 +403,9 @@
     if ( error )
       goto Exit;
 
-    /* copy advance while converting it to 16.16 format */
-    glyph->advance.x = slot->advance.x << 10;
-    glyph->advance.y = slot->advance.y << 10;
+    /* copy advance while converting 26.6 to 16.16 format */
+    glyph->advance.x = slot->advance.x * 1024;
+    glyph->advance.y = slot->advance.y * 1024;
 
     /* now import the image from the glyph slot */
     error = clazz->glyph_init( glyph, slot );
@@ -512,7 +516,7 @@
     FT_BitmapGlyph            bitmap = NULL;
     const FT_Glyph_Class*     clazz;
 
-    /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
+    /* FT_BITMAP_GLYPH_CLASS_GET dereferences `library' in PIC mode */
     FT_Library                library;
 
 
diff --git a/src/base/fthash.c b/src/base/fthash.c
new file mode 100644
index 0000000..21bc8dd
--- /dev/null
+++ b/src/base/fthash.c
@@ -0,0 +1,339 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fthash.c                                                               */
+/*                                                                         */
+/*    Hashing functions (body).                                            */
+/*                                                                         */
+/***************************************************************************/
+
+/*
+ * Copyright 2000 Computing Research Labs, New Mexico State University
+ * Copyright 2001-2015
+ *   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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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.
+ */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50     */
+  /*                                                                       */
+  /*  taken from Mark Leisher's xmbdfed package                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_HASH_H
+#include FT_INTERNAL_MEMORY_H
+
+
+#define INITIAL_HT_SIZE  241
+
+
+  static FT_ULong
+  hash_str_lookup( FT_Hashkey*  key )
+  {
+    const char*  kp  = key->str;
+    FT_ULong     res = 0;
+
+
+    /* Mocklisp hash function. */
+    while ( *kp )
+      res = ( res << 5 ) - res + (FT_ULong)*kp++;
+
+    return res;
+  }
+
+
+  static FT_ULong
+  hash_num_lookup( FT_Hashkey*  key )
+  {
+    FT_ULong  num = (FT_ULong)key->num;
+    FT_ULong  res;
+
+
+    /* Mocklisp hash function. */
+    res = num & 0xFF;
+    res = ( res << 5 ) - res + ( ( num >>  8 ) & 0xFF );
+    res = ( res << 5 ) - res + ( ( num >> 16 ) & 0xFF );
+    res = ( res << 5 ) - res + ( ( num >> 24 ) & 0xFF );
+
+    return res;
+  }
+
+
+  static FT_Bool
+  hash_str_compare( FT_Hashkey*  a,
+                    FT_Hashkey*  b )
+  {
+    if ( a->str[0] == b->str[0]           &&
+         ft_strcmp( a->str, b->str ) == 0 )
+      return 1;
+
+    return 0;
+  }
+
+
+  static FT_Bool
+  hash_num_compare( FT_Hashkey*  a,
+                    FT_Hashkey*  b )
+  {
+    if ( a->num == b->num )
+      return 1;
+
+    return 0;
+  }
+
+
+  static FT_Hashnode*
+  hash_bucket( FT_Hashkey  key,
+               FT_Hash     hash )
+  {
+    FT_ULong      res = 0;
+    FT_Hashnode*  bp  = hash->table;
+    FT_Hashnode*  ndp;
+
+
+    res = (hash->lookup)( &key );
+
+    ndp = bp + ( res % hash->size );
+    while ( *ndp )
+    {
+      if ( (hash->compare)( &(*ndp)->key, &key ) )
+        break;
+
+      ndp--;
+      if ( ndp < bp )
+        ndp = bp + ( hash->size - 1 );
+    }
+
+    return ndp;
+  }
+
+
+  static FT_Error
+  hash_rehash( FT_Hash    hash,
+               FT_Memory  memory )
+  {
+    FT_Hashnode*  obp = hash->table;
+    FT_Hashnode*  bp;
+    FT_Hashnode*  nbp;
+
+    FT_UInt   i, sz = hash->size;
+    FT_Error  error = FT_Err_Ok;
+
+
+    hash->size <<= 1;
+    hash->limit  = hash->size / 3;
+
+    if ( FT_NEW_ARRAY( hash->table, hash->size ) )
+      goto Exit;
+
+    for ( i = 0, bp = obp; i < sz; i++, bp++ )
+    {
+      if ( *bp )
+      {
+        nbp = hash_bucket( (*bp)->key, hash );
+        *nbp = *bp;
+      }
+    }
+
+    FT_FREE( obp );
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  hash_init( FT_Hash    hash,
+             FT_Bool    is_num,
+             FT_Memory  memory )
+  {
+    FT_UInt   sz = INITIAL_HT_SIZE;
+    FT_Error  error;
+
+
+    hash->size  = sz;
+    hash->limit = sz / 3;
+    hash->used  = 0;
+
+    if ( is_num )
+    {
+      hash->lookup  = hash_num_lookup;
+      hash->compare = hash_num_compare;
+    }
+    else
+    {
+      hash->lookup  = hash_str_lookup;
+      hash->compare = hash_str_compare;
+    }
+
+    FT_MEM_NEW_ARRAY( hash->table, sz );
+
+    return error;
+  }
+
+
+  FT_Error
+  ft_hash_str_init( FT_Hash    hash,
+                    FT_Memory  memory )
+  {
+    return hash_init( hash, 0, memory );
+  }
+
+
+  FT_Error
+  ft_hash_num_init( FT_Hash    hash,
+                    FT_Memory  memory )
+  {
+    return hash_init( hash, 1, memory );
+  }
+
+
+  void
+  ft_hash_str_free( FT_Hash    hash,
+                    FT_Memory  memory )
+  {
+    if ( hash )
+    {
+      FT_UInt       sz = hash->size;
+      FT_Hashnode*  bp = hash->table;
+      FT_UInt       i;
+
+
+      for ( i = 0; i < sz; i++, bp++ )
+        FT_FREE( *bp );
+
+      FT_FREE( hash->table );
+    }
+  }
+
+
+  /* `ft_hash_num_free' is the same as `ft_hash_str_free' */
+
+
+  static FT_Error
+  hash_insert( FT_Hashkey  key,
+               size_t      data,
+               FT_Hash     hash,
+               FT_Memory   memory )
+  {
+    FT_Hashnode   nn;
+    FT_Hashnode*  bp    = hash_bucket( key, hash );
+    FT_Error      error = FT_Err_Ok;
+
+
+    nn = *bp;
+    if ( !nn )
+    {
+      if ( FT_NEW( nn ) )
+        goto Exit;
+      *bp = nn;
+
+      nn->key  = key;
+      nn->data = data;
+
+      if ( hash->used >= hash->limit )
+      {
+        error = hash_rehash( hash, memory );
+        if ( error )
+          goto Exit;
+      }
+
+      hash->used++;
+    }
+    else
+      nn->data = data;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_Error
+  ft_hash_str_insert( const char*  key,
+                      size_t       data,
+                      FT_Hash      hash,
+                      FT_Memory    memory )
+  {
+    FT_Hashkey  hk;
+
+
+    hk.str = key;
+
+    return hash_insert( hk, data, hash, memory );
+  }
+
+
+  FT_Error
+  ft_hash_num_insert( FT_Int     num,
+                      size_t     data,
+                      FT_Hash    hash,
+                      FT_Memory  memory )
+  {
+    FT_Hashkey  hk;
+
+
+    hk.num = num;
+
+    return hash_insert( hk, data, hash, memory );
+  }
+
+
+  static size_t*
+  hash_lookup( FT_Hashkey  key,
+               FT_Hash     hash )
+  {
+    FT_Hashnode*  np = hash_bucket( key, hash );
+
+
+    return (*np) ? &(*np)->data
+                 : NULL;
+  }
+
+
+  size_t*
+  ft_hash_str_lookup( const char*  key,
+                      FT_Hash      hash )
+  {
+    FT_Hashkey  hk;
+
+
+    hk.str = key;
+
+    return hash_lookup( hk, hash );
+  }
+
+
+  size_t*
+  ft_hash_num_lookup( FT_Int   num,
+                      FT_Hash  hash )
+  {
+    FT_Hashkey  hk;
+
+
+    hk.num = num;
+
+    return hash_lookup( hk, hash );
+  }
+
+
+/* END */
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index 6176273..02ef938 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType initialization layer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2002, 2005, 2007, 2009, 2012, 2013 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -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  */
-  /*     `config/ftmodule.h'.  See the document `FreeType 2.0 Build        */
-  /*     System' for more information.                                     */
+  /*     `freetype/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,   */
@@ -138,7 +138,7 @@
 #include FT_CONFIG_MODULES_H
 
     FT_FREE( classes );
-    pic_container->default_module_classes = 0;
+    pic_container->default_module_classes = NULL;
   }
 
 
@@ -164,7 +164,7 @@
 
     memory = library->memory;
 
-    pic_container->default_module_classes = 0;
+    pic_container->default_module_classes = NULL;
 
     if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) *
                               ( FT_NUM_MODULE_CLASSES + 1 ) ) )
@@ -172,8 +172,8 @@
 
     /* initialize all pointers to 0, especially the last one */
     for ( i = 0; i < FT_NUM_MODULE_CLASSES; i++ )
-      classes[i] = 0;
-    classes[FT_NUM_MODULE_CLASSES] = 0;
+      classes[i] = NULL;
+    classes[FT_NUM_MODULE_CLASSES] = NULL;
 
     i = 0;
 
@@ -226,6 +226,115 @@
   }
 
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+
+#define MAX_LENGTH  128
+
+  /*
+   * Set default properties derived from the `FREETYPE_PROPERTIES'
+   * environment variable.
+   *
+   * `FREETYPE_PROPERTIES' has the following syntax form (broken here into
+   * multiple lines for better readability)
+   *
+   *   <optional whitespace>
+   *   <module-name1> ':'
+   *   <property-name1> '=' <property-value1>
+   *   <whitespace>
+   *   <module-name2> ':'
+   *   <property-name2> '=' <property-value2>
+   *   ...
+   *
+   * Example:
+   *
+   *   FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
+   *                       cff:no-stem-darkening=1 \
+   *                       autofitter:warping=1
+   *
+   */
+
+  static void
+  ft_set_default_properties( FT_Library  library )
+  {
+    const char*  env;
+    const char*  p;
+    const char*  q;
+
+    char  module_name[MAX_LENGTH + 1];
+    char  property_name[MAX_LENGTH + 1];
+    char  property_value[MAX_LENGTH + 1];
+
+    int  i;
+
+
+    env = ft_getenv( "FREETYPE_PROPERTIES" );
+    if ( !env )
+      return;
+
+    for ( p = env; *p; p++ )
+    {
+      /* skip leading whitespace and separators */
+      if ( *p == ' ' || *p == '\t' )
+        continue;
+
+      /* read module name, followed by `:' */
+      q = p;
+      for ( i = 0; i < MAX_LENGTH; i++ )
+      {
+        if ( !*p || *p == ':' )
+          break;
+        module_name[i] = *p++;
+      }
+      module_name[i] = '\0';
+
+      if ( !*p || *p != ':' || p == q )
+        break;
+
+      /* read property name, followed by `=' */
+      q = ++p;
+      for ( i = 0; i < MAX_LENGTH; i++ )
+      {
+        if ( !*p || *p == '=' )
+          break;
+        property_name[i] = *p++;
+      }
+      property_name[i] = '\0';
+
+      if ( !*p || *p != '=' || p == q )
+        break;
+
+      /* read property value, followed by whitespace (if any) */
+      q = ++p;
+      for ( i = 0; i < MAX_LENGTH; i++ )
+      {
+        if ( !*p || *p == ' ' || *p == '\t' )
+          break;
+        property_value[i] = *p++;
+      }
+      property_value[i] = '\0';
+
+      if ( !( *p == '\0' || *p == ' ' || *p == '\t' ) || p == q )
+        break;
+
+      /* we completely ignore errors */
+      ft_property_string_set( library,
+                              module_name,
+                              property_name,
+                              property_value );
+    }
+  }
+
+#else
+
+  static void
+  ft_set_default_properties( FT_Library  library )
+  {
+    FT_UNUSED( library );
+  }
+
+#endif
+
+
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Error )
@@ -235,6 +344,8 @@
     FT_Memory  memory;
 
 
+    /* check of `alibrary' delayed to `FT_New_Library' */
+
     /* First of all, allocate a new system object -- this function is part */
     /* of the system-specific component, i.e. `ftsystem.c'.                */
 
@@ -254,6 +365,8 @@
     else
       FT_Add_Default_Modules( *alibrary );
 
+    ft_set_default_properties( *alibrary );
+
     return error;
   }
 
@@ -263,17 +376,19 @@
   FT_EXPORT_DEF( FT_Error )
   FT_Done_FreeType( FT_Library  library )
   {
-    if ( library )
-    {
-      FT_Memory  memory = library->memory;
+    FT_Memory  memory;
 
 
-      /* Discard the library object */
-      FT_Done_Library( library );
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
 
-      /* discard memory manager */
-      FT_Done_Memory( memory );
-    }
+    memory = library->memory;
+
+    /* Discard the library object */
+    FT_Done_Library( library );
+
+    /* discard memory manager */
+    FT_Done_Memory( memory );
 
     return FT_Err_Ok;
   }
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 4aefb68..8bcbed7 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for color filtering of subpixel bitmap glyphs (body).   */
 /*                                                                         */
-/*  Copyright 2006, 2008-2010, 2013, 2014 by                               */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -46,6 +46,10 @@
       FT_Byte*  line = bitmap->buffer;
 
 
+      /* take care of bitmap flow */
+      if ( bitmap->pitch < 0 )
+        line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
       /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
       /* the values in `weights' can exceed 0xFF                        */
 
@@ -106,6 +110,10 @@
       FT_Int    pitch  = bitmap->pitch;
 
 
+      /* take care of bitmap flow */
+      if ( bitmap->pitch < 0 )
+        column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
       for ( ; width > 0; width--, column++ )
       {
         FT_Byte*  col = column;
@@ -174,7 +182,7 @@
     FT_UInt  height = (FT_UInt)bitmap->rows;
     FT_Int   pitch  = bitmap->pitch;
 
-    static const int  filters[3][3] =
+    static const unsigned int  filters[3][3] =
     {
       { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
       { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
@@ -190,6 +198,10 @@
       FT_Byte*  line = bitmap->buffer;
 
 
+      /* take care of bitmap flow */
+      if ( bitmap->pitch < 0 )
+        line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
       for ( ; height > 0; height--, line += pitch )
       {
         FT_UInt  xx;
@@ -229,10 +241,14 @@
       FT_Byte*  column = bitmap->buffer;
 
 
+      /* take care of bitmap flow */
+      if ( bitmap->pitch < 0 )
+        column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
       for ( ; width > 0; width--, column++ )
       {
         FT_Byte*  col     = column;
-        FT_Byte*  col_end = col + height * pitch;
+        FT_Byte*  col_end = col + (FT_Int)height * pitch;
 
 
         for ( ; col < col_end; col += 3 * pitch )
@@ -273,10 +289,15 @@
   FT_Library_SetLcdFilterWeights( FT_Library      library,
                                   unsigned char  *weights )
   {
-    if ( !library || !weights )
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
+    if ( !weights )
       return FT_THROW( Invalid_Argument );
 
     ft_memcpy( library->lcd_weights, weights, 5 );
+    library->lcd_filter_func = _ft_lcd_filter_fir;
+    library->lcd_extra       = 2;
 
     return FT_Err_Ok;
   }
@@ -286,16 +307,14 @@
   FT_Library_SetLcdFilter( FT_Library    library,
                            FT_LcdFilter  filter )
   {
+    static const FT_Byte  default_filter[5] =
+                            { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
     static const FT_Byte  light_filter[5] =
                             { 0x00, 0x55, 0x56, 0x55, 0x00 };
-    /* the values here sum up to a value larger than 256, */
-    /* providing a cheap gamma correction                 */
-    static const FT_Byte  default_filter[5] =
-                            { 0x10, 0x40, 0x70, 0x40, 0x10 };
 
 
     if ( !library )
-      return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Library_Handle );
 
     switch ( filter )
     {
@@ -305,25 +324,9 @@
       break;
 
     case FT_LCD_FILTER_DEFAULT:
-#if defined( FT_FORCE_LEGACY_LCD_FILTER )
-
-      library->lcd_filter_func = _ft_lcd_filter_legacy;
-      library->lcd_extra       = 0;
-
-#elif defined( FT_FORCE_LIGHT_LCD_FILTER )
-
-      ft_memcpy( library->lcd_weights, light_filter, 5 );
-      library->lcd_filter_func = _ft_lcd_filter_fir;
-      library->lcd_extra       = 2;
-
-#else
-
       ft_memcpy( library->lcd_weights, default_filter, 5 );
       library->lcd_filter_func = _ft_lcd_filter_fir;
       library->lcd_extra       = 2;
-
-#endif
-
       break;
 
     case FT_LCD_FILTER_LIGHT:
@@ -335,6 +338,7 @@
 #ifdef USE_LEGACY
 
     case FT_LCD_FILTER_LEGACY:
+    case FT_LCD_FILTER_LEGACY1:
       library->lcd_filter_func = _ft_lcd_filter_legacy;
       library->lcd_extra       = 0;
       break;
diff --git a/src/base/ftmm.c b/src/base/ftmm.c
index 18ff879..6b759ca 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Multiple Master font support (body).                                 */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2009, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -72,6 +72,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !amaster )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
@@ -94,6 +99,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !amaster )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
@@ -117,6 +127,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
@@ -140,6 +155,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
@@ -163,6 +183,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
@@ -189,6 +214,11 @@
     FT_Service_MultiMasters  service;
 
 
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index cc56105..9006b59 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (body).                            */
 /*                                                                         */
-/*  Copyright 1996-2014 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -55,7 +55,18 @@
 #pragma warning( disable : 4244 )
 #endif /* _MSC_VER */
 
-  /* it's easiest to include `md5.c' directly */
+  /* It's easiest to include `md5.c' directly.  However, since OpenSSL */
+  /* also provides the same functions, there might be conflicts if     */
+  /* both FreeType and OpenSSL are built as static libraries.  For     */
+  /* this reason, we put the MD5 stuff into the `FT_' namespace.       */
+#define MD5_u32plus  FT_MD5_u32plus
+#define MD5_CTX      FT_MD5_CTX
+#define MD5_Init     FT_MD5_Init
+#define MD5_Update   FT_MD5_Update
+#define MD5_Final    FT_MD5_Final
+
+#undef  HAVE_OPENSSL
+
 #include "md5.c"
 
 #if defined( _MSC_VER )
@@ -158,7 +169,7 @@
     FT_Stream  stream = NULL;
 
 
-    *astream = 0;
+    *astream = NULL;
 
     if ( !library )
       return FT_THROW( Invalid_Library_Handle );
@@ -178,7 +189,7 @@
       /* create a memory-based stream */
       FT_Stream_OpenMemory( stream,
                             (const FT_Byte*)args->memory_base,
-                            args->memory_size );
+                            (FT_ULong)args->memory_size );
     }
 
 #ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
@@ -353,10 +364,10 @@
     slot->bitmap_left   = 0;
     slot->bitmap_top    = 0;
     slot->num_subglyphs = 0;
-    slot->subglyphs     = 0;
-    slot->control_data  = 0;
+    slot->subglyphs     = NULL;
+    slot->control_data  = NULL;
     slot->control_len   = 0;
-    slot->other         = 0;
+    slot->other         = NULL;
     slot->format        = FT_GLYPH_FORMAT_NONE;
 
     slot->linearHoriAdvance = 0;
@@ -387,7 +398,7 @@
       if ( FT_DRIVER_USES_OUTLINES( driver ) )
       {
         FT_GlyphLoader_Done( slot->internal->loader );
-        slot->internal->loader = 0;
+        slot->internal->loader = NULL;
       }
 
       FT_FREE( slot->internal );
@@ -408,7 +419,10 @@
     FT_GlyphSlot     slot = NULL;
 
 
-    if ( !face || !face->driver )
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
+
+    if ( !face->driver )
       return FT_THROW( Invalid_Argument );
 
     driver = face->driver;
@@ -435,7 +449,7 @@
         *aslot = slot;
     }
     else if ( aslot )
-      *aslot = 0;
+      *aslot = NULL;
 
 
   Exit:
@@ -508,6 +522,7 @@
       internal->transform_matrix.xy = 0;
       internal->transform_matrix.yx = 0;
       internal->transform_matrix.yy = 0x10000L;
+
       matrix = &internal->transform_matrix;
     }
     else
@@ -523,6 +538,7 @@
     {
       internal->transform_delta.x = 0;
       internal->transform_delta.y = 0;
+
       delta = &internal->transform_delta;
     }
     else
@@ -670,8 +686,8 @@
         /* 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           ||
+        if ( ( mode == FT_RENDER_MODE_LIGHT                   &&
+               !FT_DRIVER_HINTS_LIGHTLY( driver ) )             ||
              ( FT_IS_SFNT( face )                             &&
                ttface->num_locations                          &&
                ttface->max_profile.maxSizeOfInstructions == 0 &&
@@ -927,7 +943,7 @@
                       (FT_List_Destructor)destroy_size,
                       memory,
                       driver );
-    face->size = 0;
+    face->size = NULL;
 
     /* now discard client data */
     if ( face->generic.finalizer )
@@ -945,7 +961,7 @@
       face->stream,
       ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
 
-    face->stream = 0;
+    face->stream = NULL;
 
     /* get rid of it */
     if ( face->internal )
@@ -963,10 +979,6 @@
                       (FT_List_Destructor)destroy_face,
                       driver->root.memory,
                       driver );
-
-    /* check whether we need to drop the driver's glyph loader */
-    if ( FT_DRIVER_USES_OUTLINES( driver ) )
-      FT_GlyphLoader_Done( driver->glyph_loader );
   }
 
 
@@ -1040,14 +1052,6 @@
              ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
                cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32    ) )
         {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-          if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
-          {
-            FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
-                       "at too late position (%d)\n", cur - first ));
-            continue;
-          }
-#endif
           face->charmap = cur[0];
           return FT_Err_Ok;
         }
@@ -1062,14 +1066,6 @@
     {
       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
       {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
-                     "at too late position (%d)\n", cur - first ));
-          continue;
-        }
-#endif
         face->charmap = cur[0];
         return FT_Err_Ok;
       }
@@ -1111,17 +1107,7 @@
       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
            FT_Get_CMap_Format( cur[0] ) == 14                  )
-      {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
-                     "at too late position (%d)\n", cur - first ));
-          continue;
-        }
-#endif
         return cur[0];
-      }
     }
 
     return NULL;
@@ -1178,7 +1164,7 @@
       int  i;
 
 
-      face->internal->incremental_interface = 0;
+      face->internal->incremental_interface = NULL;
       for ( i = 0; i < num_params && !face->internal->incremental_interface;
             i++ )
         if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
@@ -1220,7 +1206,7 @@
         clazz->done_face( face );
       FT_FREE( internal );
       FT_FREE( face );
-      *aface = 0;
+      *aface = NULL;
     }
 
     return error;
@@ -1243,7 +1229,7 @@
     FT_Open_Args  args;
 
 
-    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+    /* test for valid `library' and `aface' delayed to `FT_Open_Face' */
     if ( !pathname )
       return FT_THROW( Invalid_Argument );
 
@@ -1269,7 +1255,7 @@
     FT_Open_Args  args;
 
 
-    /* test for valid `library' and `face' delayed to FT_Open_Face() */
+    /* test for valid `library' and `face' delayed to `FT_Open_Face' */
     if ( !file_base )
       return FT_THROW( Invalid_Argument );
 
@@ -1323,8 +1309,8 @@
     FT_FREE( stream->base );
 
     stream->size  = 0;
-    stream->base  = 0;
-    stream->close = 0;
+    stream->base  = NULL;
+    stream->close = NULL;
   }
 
 
@@ -1348,7 +1334,7 @@
     if ( !base )
       return FT_THROW( Invalid_Argument );
 
-    *astream = 0;
+    *astream = NULL;
     memory = library->memory;
     if ( FT_NEW( stream ) )
       goto Exit;
@@ -1400,13 +1386,13 @@
     }
 
 #ifdef FT_MACINTOSH
-    /* At this point, face_index has served its purpose;      */
+    /* At this point, the face index has served its purpose;  */
     /* whoever calls this function has already used it to     */
     /* locate the correct font data.  We should not propagate */
     /* this index to FT_Open_Face() (unless it is negative).  */
 
     if ( face_index > 0 )
-      face_index = 0;
+      face_index &= 0x7FFF0000L; /* retain GX data */
 #endif
 
     error = FT_Open_Face( library, &args, face_index, aface );
@@ -1432,7 +1418,7 @@
 
   /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
   /* format too.  Here, since we can't expect that the TrueType font */
-  /* driver is loaded unconditially, we must parse the font by       */
+  /* driver is loaded unconditionally, we must parse the font by     */
   /* ourselves.  We are only interested in the name of the table and */
   /* the offset.                                                     */
 
@@ -1497,6 +1483,7 @@
       if ( face_index >= 0 && pstable_index == face_index )
         return FT_Err_Ok;
     }
+
     return FT_THROW( Table_Missing );
   }
 
@@ -1512,7 +1499,7 @@
     FT_Error   error;
     FT_Memory  memory = library->memory;
     FT_ULong   offset, length;
-    FT_Long    pos;
+    FT_ULong   pos;
     FT_Bool    is_sfnt_cid;
     FT_Byte*   sfnt_ps = NULL;
 
@@ -1520,7 +1507,11 @@
     FT_UNUSED( params );
 
 
-    pos = FT_Stream_Pos( stream );
+    /* ignore GX stuff */
+    if ( face_index > 0 )
+      face_index &= 0xFFFFL;
+
+    pos = FT_STREAM_POS();
 
     error = ft_lookup_PS_in_sfnt_stream( stream,
                                          face_index,
@@ -1530,7 +1521,21 @@
     if ( error )
       goto Exit;
 
-    if ( FT_Stream_Seek( stream, pos + offset ) )
+    if ( offset > stream->size )
+    {
+      FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table offset\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+    else if ( length > stream->size - offset )
+    {
+      FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table length\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    error = FT_Stream_Seek( stream, pos + offset );
+    if ( error )
       goto Exit;
 
     if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
@@ -1538,7 +1543,10 @@
 
     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
     if ( error )
+    {
+      FT_FREE( sfnt_ps );
       goto Exit;
+    }
 
     error = open_face_from_buffer( library,
                                    sfnt_ps,
@@ -1583,9 +1591,9 @@
     FT_Memory  memory = library->memory;
     FT_Byte*   pfb_data = NULL;
     int        i, type, flags;
-    FT_Long    len;
-    FT_Long    pfb_len, pfb_pos, pfb_lenpos;
-    FT_Long    rlen, temp;
+    FT_ULong   len;
+    FT_ULong   pfb_len, pfb_pos, pfb_lenpos;
+    FT_ULong   rlen, temp;
 
 
     if ( face_index == -1 )
@@ -1598,14 +1606,39 @@
     pfb_len = 0;
     for ( i = 0; i < resource_cnt; ++i )
     {
-      error = FT_Stream_Seek( stream, offsets[i] );
+      error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
       if ( error )
         goto Exit;
-      if ( FT_READ_LONG( temp ) )
+      if ( FT_READ_ULONG( temp ) )
         goto Exit;
+
+      /* FT2 allocator takes signed long buffer length,
+       * too large value causing overflow should be checked
+       */
+      FT_TRACE4(( "                 POST fragment #%d: length=0x%08x"
+                  " total pfb_len=0x%08x\n",
+                  i, temp, pfb_len + temp + 6));
+      if ( FT_MAC_RFORK_MAX_LEN < temp               ||
+           FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 )
+      {
+        FT_TRACE2(( "             MacOS resource length cannot exceed"
+                    " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
+        error = FT_THROW( Invalid_Offset );
+        goto Exit;
+      }
+
       pfb_len += temp + 6;
     }
 
+    FT_TRACE2(( "             total buffer size to concatenate %d"
+                " POST fragments: 0x%08x\n",
+                 resource_cnt, pfb_len + 2));
+    if ( pfb_len + 2 < 6 ) {
+      FT_TRACE2(( "             too long fragment length makes"
+                  " pfb_len confused: pfb_len=0x%08x\n", pfb_len ));
+      error = FT_THROW( Array_Too_Large );
+      goto Exit;
+    }
     if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
       goto Exit;
 
@@ -1622,19 +1655,33 @@
     type = 1;
     for ( i = 0; i < resource_cnt; ++i )
     {
-      error = FT_Stream_Seek( stream, offsets[i] );
+      error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
       if ( error )
         goto Exit2;
-      if ( FT_READ_LONG( rlen ) )
-        goto Exit;
+      if ( FT_READ_ULONG( rlen ) )
+        goto Exit2;
+
+      /* FT2 allocator takes signed long buffer length,
+       * too large fragment length causing overflow should be checked
+       */
+      if ( 0x7FFFFFFFUL < rlen )
+      {
+        error = FT_THROW( Invalid_Offset );
+        goto Exit2;
+      }
+
       if ( FT_READ_USHORT( flags ) )
-        goto Exit;
+        goto Exit2;
       FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
                    i, offsets[i], rlen, flags ));
 
+      error = FT_ERR( Array_Too_Large );
       /* postpone the check of rlen longer than buffer until FT_Stream_Read() */
       if ( ( flags >> 8 ) == 0 )        /* Comment, should not be loaded */
+      {
+        FT_TRACE3(( "    Skip POST fragment #%d because it is a comment\n", i ));
         continue;
+      }
 
       /* the flags are part of the resource, so rlen >= 2.  */
       /* but some fonts declare rlen = 0 for empty fragment */
@@ -1647,6 +1694,8 @@
         len += rlen;
       else
       {
+        FT_TRACE3(( "    Write POST fragment #%d header (4-byte) to buffer"
+                    " %p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
         if ( pfb_lenpos + 3 > pfb_len + 2 )
           goto Exit2;
         pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
@@ -1657,6 +1706,8 @@
         if ( ( flags >> 8 ) == 5 )      /* End of font mark */
           break;
 
+        FT_TRACE3(( "    Write POST fragment #%d header (6-byte) to buffer"
+                    " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
         if ( pfb_pos + 6 > pfb_len + 2 )
           goto Exit2;
         pfb_data[pfb_pos++] = 0x80;
@@ -1672,16 +1723,18 @@
         pfb_data[pfb_pos++] = 0;
       }
 
-      error = FT_ERR( Cannot_Open_Resource );
       if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
         goto Exit2;
 
+      FT_TRACE3(( "    Load POST fragment #%d (%d byte) to buffer"
+                  " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
       if ( error )
         goto Exit2;
       pfb_pos += rlen;
     }
 
+    error = FT_ERR( Array_Too_Large );
     if ( pfb_pos + 2 > pfb_len + 2 )
       goto Exit2;
     pfb_data[pfb_pos++] = 0x80;
@@ -1702,6 +1755,13 @@
                                   aface );
 
   Exit2:
+    if ( error == FT_ERR( Array_Too_Large ) )
+      FT_TRACE2(( "  Abort due to too-short buffer to store"
+                  " all POST fragments\n" ));
+    else if ( error == FT_ERR( Invalid_Offset ) )
+      FT_TRACE2(( "  Abort due to invalid offset in a POST fragment\n" ));
+    if ( error )
+      error = FT_ERR( Cannot_Open_Resource );
     FT_FREE( pfb_data );
 
   Exit:
@@ -1712,7 +1772,7 @@
   /* The resource header says we've got resource_cnt `sfnt'      */
   /* (TrueType/OpenType) resources in this file.  Look through   */
   /* them for the one indicated by face_index, load it into mem, */
-  /* pass it on the the truetype driver and return it.           */
+  /* pass it on to the truetype driver, and return it.           */
   /*                                                             */
   static FT_Error
   Mac_Read_sfnt_Resource( FT_Library  library,
@@ -1725,18 +1785,18 @@
     FT_Memory  memory = library->memory;
     FT_Byte*   sfnt_data = NULL;
     FT_Error   error;
-    FT_Long    flag_offset;
+    FT_ULong   flag_offset;
     FT_Long    rlen;
     int        is_cff;
     FT_Long    face_index_in_resource = 0;
 
 
-    if ( face_index == -1 )
-      face_index = 0;
+    if ( face_index < 0 )
+      face_index = -face_index - 1;
     if ( face_index >= resource_cnt )
       return FT_THROW( Cannot_Open_Resource );
 
-    flag_offset = offsets[face_index];
+    flag_offset = (FT_ULong)offsets[face_index];
     error = FT_Stream_Seek( stream, flag_offset );
     if ( error )
       goto Exit;
@@ -1745,6 +1805,8 @@
       goto Exit;
     if ( rlen == -1 )
       return FT_THROW( Cannot_Open_Resource );
+    if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN )
+      return FT_THROW( Invalid_Offset );
 
     error = open_face_PS_from_sfnt_stream( library,
                                            stream,
@@ -1755,19 +1817,22 @@
       goto Exit;
 
     /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
-    if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
-      goto Exit;
-
-    if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
-      return error;
-    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
+    error = FT_Stream_Seek( stream, flag_offset + 4 );
     if ( error )
       goto Exit;
 
+    if ( FT_ALLOC( sfnt_data, rlen ) )
+      return error;
+    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen );
+    if ( error ) {
+      FT_FREE( sfnt_data );
+      goto Exit;
+    }
+
     is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
     error = open_face_from_buffer( library,
                                    sfnt_data,
-                                   rlen,
+                                   (FT_ULong)rlen,
                                    face_index_in_resource,
                                    is_cff ? "cff" : "truetype",
                                    aface );
@@ -1864,13 +1929,14 @@
     if ( error )
       goto Exit;
 
-    if (            header[ 0] !=  0 ||
-                    header[74] !=  0 ||
-                    header[82] !=  0 ||
-                    header[ 1] ==  0 ||
-                    header[ 1] >  33 ||
-                    header[63] !=  0 ||
-         header[2 + header[1]] !=  0 )
+    if (            header[ 0] !=   0 ||
+                    header[74] !=   0 ||
+                    header[82] !=   0 ||
+                    header[ 1] ==   0 ||
+                    header[ 1] >   33 ||
+                    header[63] !=   0 ||
+         header[2 + header[1]] !=   0 ||
+                  header[0x53] > 0x7F )
       return FT_THROW( Unknown_File_Format );
 
     dlen = ( header[0x53] << 24 ) |
@@ -1881,7 +1947,7 @@
     rlen = ( header[0x57] << 24 ) |
            ( header[0x58] << 16 ) |
            ( header[0x59] <<  8 ) |
-             header[0x5a];
+             header[0x5A];
 #endif /* 0 */
     offset = 128 + ( ( dlen + 127 ) & ~127 );
 
@@ -1905,7 +1971,7 @@
 
     FT_Memory  memory = library->memory;
     FT_Error   error  = FT_ERR( Unknown_File_Format );
-    int        i;
+    FT_UInt    i;
 
     char *     file_names[FT_RACCESS_N_RULES];
     FT_Long    offsets[FT_RACCESS_N_RULES];
@@ -1913,7 +1979,7 @@
     FT_Bool    is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
 
     FT_Open_Args  args2;
-    FT_Stream     stream2 = 0;
+    FT_Stream     stream2 = NULL;
 
 
     FT_Raccess_Guess( library, stream,
@@ -2007,7 +2073,11 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_raccess
 
-      FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+      FT_TRACE3(( "Try as dfont: " ));
+      if ( !( args->flags & FT_OPEN_MEMORY ) )
+        FT_TRACE3(( "%s ...", args->pathname ));
+#endif
 
       error = IsMacResource( library, stream, 0, face_index, aface );
 
@@ -2049,8 +2119,7 @@
     FT_Module*   limit;
 
 
-    /* test for valid `library' delayed to */
-    /* FT_Stream_New()                     */
+    /* test for valid `library' delayed to `FT_Stream_New' */
 
     if ( ( !aface && face_index >= 0 ) || !args )
       return FT_THROW( Invalid_Argument );
@@ -2075,7 +2144,7 @@
       if ( FT_MODULE_IS_DRIVER( driver ) )
       {
         FT_Int         num_params = 0;
-        FT_Parameter*  params     = 0;
+        FT_Parameter*  params     = NULL;
 
 
         if ( args->flags & FT_OPEN_PARAMS )
@@ -2109,7 +2178,7 @@
         if ( FT_MODULE_IS_DRIVER( cur[0] ) )
         {
           FT_Int         num_params = 0;
-          FT_Parameter*  params     = 0;
+          FT_Parameter*  params     = NULL;
 
 
           driver = FT_DRIVER( cur[0] );
@@ -2130,7 +2199,8 @@
                FT_ERR_EQ( error, Table_Missing )                        )
           {
             /* TrueType but essential tables are missing */
-            if ( FT_Stream_Seek( stream, 0 ) )
+            error = FT_Stream_Seek( stream, 0 );
+            if ( error )
               break;
 
             error = open_face_PS_from_sfnt_stream( library,
@@ -2244,11 +2314,24 @@
 
 
         if ( bsize->height < 0 )
-          bsize->height = (FT_Short)-bsize->height;
+          bsize->height = -bsize->height;
         if ( bsize->x_ppem < 0 )
-          bsize->x_ppem = (FT_Short)-bsize->x_ppem;
+          bsize->x_ppem = -bsize->x_ppem;
         if ( bsize->y_ppem < 0 )
           bsize->y_ppem = -bsize->y_ppem;
+
+        /* check whether negation actually has worked */
+        if ( bsize->height < 0 || bsize->x_ppem < 0 || bsize->y_ppem < 0 )
+        {
+          FT_TRACE0(( "FT_Open_Face:"
+                      " Invalid bitmap dimensions for stroke %d,"
+                      " now disabled\n", i ));
+          bsize->width  = 0;
+          bsize->height = 0;
+          bsize->size   = 0;
+          bsize->x_ppem = 0;
+          bsize->y_ppem = 0;
+        }
       }
     }
 
@@ -2297,7 +2380,7 @@
     FT_Open_Args  open;
 
 
-    /* test for valid `face' delayed to FT_Attach_Stream() */
+    /* test for valid `face' delayed to `FT_Attach_Stream' */
 
     if ( !filepathname )
       return FT_THROW( Invalid_Argument );
@@ -2323,7 +2406,7 @@
     FT_Driver_Class  clazz;
 
 
-    /* test for valid `parameters' delayed to FT_Stream_New() */
+    /* test for valid `parameters' delayed to `FT_Stream_New' */
 
     if ( !face )
       return FT_THROW( Invalid_Face_Handle );
@@ -2359,6 +2442,9 @@
   FT_EXPORT_DEF( FT_Error )
   FT_Reference_Face( FT_Face  face )
   {
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
+
     face->internal->refcount++;
 
     return FT_Err_Ok;
@@ -2417,20 +2503,20 @@
     FT_Driver        driver;
     FT_Driver_Class  clazz;
 
-    FT_Size          size = 0;
-    FT_ListNode      node = 0;
+    FT_Size          size = NULL;
+    FT_ListNode      node = NULL;
 
 
     if ( !face )
       return FT_THROW( Invalid_Face_Handle );
 
     if ( !asize )
-      return FT_THROW( Invalid_Size_Handle );
+      return FT_THROW( Invalid_Argument );
 
     if ( !face->driver )
       return FT_THROW( Invalid_Driver_Handle );
 
-    *asize = 0;
+    *asize = NULL;
 
     driver = face->driver;
     clazz  = driver->clazz;
@@ -2443,7 +2529,7 @@
     size->face = face;
 
     /* for now, do not use any internal fields in size objects */
-    size->internal = 0;
+    size->internal = NULL;
 
     if ( clazz->init_size )
       error = clazz->init_size( size );
@@ -2501,7 +2587,7 @@
 
       if ( face->size == size )
       {
-        face->size = 0;
+        face->size = NULL;
         if ( face->sizes_list.head )
           face->size = (FT_Size)(face->sizes_list.head->data);
       }
@@ -2545,6 +2631,9 @@
     w = FT_PIX_ROUND( w );
     h = FT_PIX_ROUND( h );
 
+    if ( !w || !h )
+      return FT_THROW( Invalid_Pixel_Size );
+
     for ( i = 0; i < face->num_fixed_sizes; i++ )
     {
       FT_Bitmap_Size*  bsize = face->available_sizes + i;
@@ -2564,6 +2653,8 @@
       }
     }
 
+    FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ));
+
     return FT_THROW( Invalid_Pixel_Size );
   }
 
@@ -2934,6 +3025,8 @@
     FT_Size_RequestRec  req;
 
 
+    /* check of `face' delayed to `FT_Request_Size' */
+
     if ( !char_width )
       char_width = char_height;
     else if ( !char_height )
@@ -2972,6 +3065,8 @@
     FT_Size_RequestRec  req;
 
 
+    /* check of `face' delayed to `FT_Request_Size' */
+
     if ( pixel_width == 0 )
       pixel_width = pixel_height;
     else if ( pixel_height == 0 )
@@ -2983,14 +3078,14 @@
       pixel_height = 1;
 
     /* use `>=' to avoid potential compiler warning on 16bit platforms */
-    if ( pixel_width  >= 0xFFFFU )
-      pixel_width  = 0xFFFFU;
+    if ( pixel_width >= 0xFFFFU )
+      pixel_width = 0xFFFFU;
     if ( pixel_height >= 0xFFFFU )
       pixel_height = 0xFFFFU;
 
     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
-    req.width          = pixel_width << 6;
-    req.height         = pixel_height << 6;
+    req.width          = (FT_Long)( pixel_width << 6 );
+    req.height         = (FT_Long)( pixel_height << 6 );
     req.horiResolution = 0;
     req.vertResolution = 0;
 
@@ -3037,18 +3132,37 @@
 
           if ( kern_mode != FT_KERNING_UNFITTED )
           {
+            FT_Pos  orig_x = akerning->x;
+            FT_Pos  orig_y = akerning->y;
+
+
             /* we scale down kerning values for small ppem values */
             /* to avoid that rounding makes them too big.         */
             /* `25' has been determined heuristically.            */
             if ( face->size->metrics.x_ppem < 25 )
-              akerning->x = FT_MulDiv( akerning->x,
+              akerning->x = FT_MulDiv( orig_x,
                                        face->size->metrics.x_ppem, 25 );
             if ( face->size->metrics.y_ppem < 25 )
-              akerning->y = FT_MulDiv( akerning->y,
+              akerning->y = FT_MulDiv( orig_y,
                                        face->size->metrics.y_ppem, 25 );
 
             akerning->x = FT_PIX_ROUND( akerning->x );
             akerning->y = FT_PIX_ROUND( akerning->y );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+            {
+              FT_Pos  orig_x_rounded = FT_PIX_ROUND( orig_x );
+              FT_Pos  orig_y_rounded = FT_PIX_ROUND( orig_y );
+
+
+              if ( akerning->x != orig_x_rounded ||
+                   akerning->y != orig_y_rounded )
+                FT_TRACE5(( "FT_Get_Kerning: horizontal kerning"
+                            " (%d, %d) scaled down to (%d, %d) pixels\n",
+                            orig_x_rounded / 64, orig_y_rounded / 64,
+                            akerning->x / 64, akerning->y / 64 ));
+            }
+#endif
           }
         }
       }
@@ -3122,15 +3236,6 @@
     {
       if ( cur[0]->encoding == encoding )
       {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
-                     "but in too late position to cache\n",
-                     cur - face->charmaps ));
-          continue;
-        }
-#endif
         face->charmap = cur[0];
         return 0;
       }
@@ -3154,8 +3259,9 @@
       return FT_THROW( Invalid_Face_Handle );
 
     cur = face->charmaps;
-    if ( !cur )
+    if ( !cur || !charmap )
       return FT_THROW( Invalid_CharMap_Handle );
+
     if ( FT_Get_CMap_Format( charmap ) == 14 )
       return FT_THROW( Invalid_Argument );
 
@@ -3165,19 +3271,11 @@
     {
       if ( cur[0] == charmap )
       {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
-                     "but in too late position to cache\n",
-                     cur - face->charmaps ));
-          continue;
-        }
-#endif
         face->charmap = cur[0];
-        return 0;
+        return FT_Err_Ok;
       }
     }
+
     return FT_THROW( Invalid_Argument );
   }
 
@@ -3199,15 +3297,6 @@
 
     FT_ASSERT( i < charmap->face->num_charmaps );
 
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-    if ( i > FT_MAX_CHARMAP_CACHEABLE )
-    {
-      FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
-                 "but in too late position to cache\n",
-                 i ));
-      return -i;
-    }
-#endif
     return i;
   }
 
@@ -3344,8 +3433,12 @@
         FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
         FT_TRACE1(( " 0x%x is truncated\n", charcode ));
       }
+
       result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
+      if ( result >= (FT_UInt)face->num_glyphs )
+        result = 0;
     }
+
     return result;
   }
 
@@ -3364,7 +3457,7 @@
     if ( face && face->charmap && face->num_glyphs )
     {
       gindex = FT_Get_Char_Index( face, 0 );
-      if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
+      if ( gindex == 0 )
         result = FT_Get_Next_Char( face, 0, &gindex );
     }
 
@@ -3418,8 +3511,9 @@
     FT_UInt  result = 0;
 
 
-    if ( face && face->charmap &&
-        face->charmap->encoding == FT_ENCODING_UNICODE )
+    if ( face                                           &&
+         face->charmap                                  &&
+         face->charmap->encoding == FT_ENCODING_UNICODE )
     {
       FT_CharMap  charmap = find_variant_selector_charmap( face );
       FT_CMap     ucmap = FT_CMAP( face->charmap );
@@ -3597,7 +3691,9 @@
     FT_UInt  result = 0;
 
 
-    if ( face && FT_HAS_GLYPH_NAMES( face ) )
+    if ( face                       &&
+         FT_HAS_GLYPH_NAMES( face ) &&
+         glyph_name                 )
     {
       FT_Service_GlyphDict  service;
 
@@ -3622,27 +3718,30 @@
                      FT_Pointer  buffer,
                      FT_UInt     buffer_max )
   {
-    FT_Error  error = FT_ERR( Invalid_Argument );
+    FT_Error              error;
+    FT_Service_GlyphDict  service;
 
 
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
+
+    if ( !buffer || buffer_max == 0 )
+      return FT_THROW( Invalid_Argument );
+
     /* clean up buffer */
-    if ( buffer && buffer_max > 0 )
-      ((FT_Byte*)buffer)[0] = 0;
+    ((FT_Byte*)buffer)[0] = '\0';
 
-    if ( face                                     &&
-         (FT_Long)glyph_index <= face->num_glyphs &&
-         FT_HAS_GLYPH_NAMES( face )               )
-    {
-      FT_Service_GlyphDict  service;
+    if ( (FT_Long)glyph_index >= face->num_glyphs )
+      return FT_THROW( Invalid_Glyph_Index );
 
+    if ( !FT_HAS_GLYPH_NAMES( face ) )
+      return FT_THROW( Invalid_Argument );
 
-      FT_FACE_LOOKUP_SERVICE( face,
-                              service,
-                              GLYPH_DICT );
-
-      if ( service && service->get_name )
-        error = service->get_name( face, glyph_index, buffer, buffer_max );
-    }
+    FT_FACE_LOOKUP_SERVICE( face, service, GLYPH_DICT );
+    if ( service && service->get_name )
+      error = service->get_name( face, glyph_index, buffer, buffer_max );
+    else
+      error = FT_THROW( Invalid_Argument );
 
     return error;
   }
@@ -3683,7 +3782,7 @@
   FT_Get_Sfnt_Table( FT_Face      face,
                      FT_Sfnt_Tag  tag )
   {
-    void*                  table = 0;
+    void*                  table = NULL;
     FT_Service_SFNT_Table  service;
 
 
@@ -3733,6 +3832,8 @@
     FT_ULong               offset;
 
 
+    /* test for valid `length' delayed to `service->table_info' */
+
     if ( !face || !FT_IS_SFNT( face ) )
       return FT_THROW( Invalid_Face_Handle );
 
@@ -3800,12 +3901,12 @@
     FT_Face  face;
 
 
-    if ( size == NULL )
-      return FT_THROW( Invalid_Argument );
+    if ( !size )
+      return FT_THROW( Invalid_Size_Handle );
 
     face = size->face;
-    if ( face == NULL || face->driver == NULL )
-      return FT_THROW( Invalid_Argument );
+    if ( !face || !face->driver )
+      return FT_THROW( Invalid_Face_Handle );
 
     /* we don't need anything more complex than that; all size objects */
     /* are already listed by the face                                  */
@@ -3834,7 +3935,7 @@
                       FT_ListNode*     node )
   {
     FT_ListNode  cur;
-    FT_Renderer  result = 0;
+    FT_Renderer  result = NULL;
 
 
     if ( !library )
@@ -3846,7 +3947,7 @@
     {
       if ( *node )
         cur = (*node)->next;
-      *node = 0;
+      *node = NULL;
     }
 
     while ( cur )
@@ -3984,7 +4085,7 @@
   FT_Get_Renderer( FT_Library       library,
                    FT_Glyph_Format  format )
   {
-    /* test for valid `library' delayed to FT_Lookup_Renderer() */
+    /* test for valid `library' delayed to `FT_Lookup_Renderer' */
 
     return FT_Lookup_Renderer( library, format, 0 );
   }
@@ -4001,12 +4102,26 @@
     FT_ListNode  node;
     FT_Error     error = FT_Err_Ok;
 
+    FT_Renderer_SetModeFunc  set_mode;
+
 
     if ( !library )
-      return FT_THROW( Invalid_Library_Handle );
+    {
+      error = FT_THROW( Invalid_Library_Handle );
+      goto Exit;
+    }
 
     if ( !renderer )
-      return FT_THROW( Invalid_Argument );
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( num_params > 0 && !parameters )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
 
     node = FT_List_Find( &library->renderers, renderer );
     if ( !node )
@@ -4020,18 +4135,14 @@
     if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
       library->cur_renderer = renderer;
 
-    if ( num_params > 0 )
+    set_mode = renderer->clazz->set_mode;
+
+    for ( ; num_params > 0; num_params-- )
     {
-      FT_Renderer_SetModeFunc  set_mode = renderer->clazz->set_mode;
-
-
-      for ( ; num_params > 0; num_params-- )
-      {
-        error = set_mode( renderer, parameters->tag, parameters->data );
-        if ( error )
-          break;
-        parameters++;
-      }
+      error = set_mode( renderer, parameters->tag, parameters->data );
+      if ( error )
+        break;
+      parameters++;
     }
 
   Exit:
@@ -4056,8 +4167,7 @@
 
     default:
       {
-        FT_ListNode  node   = 0;
-        FT_Bool      update = 0;
+        FT_ListNode  node = NULL;
 
 
         /* small shortcut for the very common case */
@@ -4084,13 +4194,7 @@
           /* now, look for another renderer that supports the same */
           /* format.                                               */
           renderer = FT_Lookup_Renderer( library, slot->format, &node );
-          update   = 1;
         }
-
-        /* if we changed the current renderer for the glyph image format */
-        /* we need to select it as the next current one                  */
-        if ( !error && update && renderer )
-          FT_Set_Renderer( library, renderer, 0, 0 );
       }
     }
 
@@ -4099,35 +4203,51 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_bitmap
 
-    /* we convert to a single bitmap format for computing the checksum */
+    /*
+     * Computing the MD5 checksum is expensive, unnecessarily distorting a
+     * possible profiling of FreeType if compiled with tracing support.  For
+     * this reason, we execute the following code only if explicitly
+     * requested.
+     */
+
+    /* we use FT_TRACE3 in this block */
+    if ( ft_trace_levels[trace_bitmap] >= 3 )
     {
-      FT_Bitmap  bitmap;
-      FT_Error   err;
-
-
-      FT_Bitmap_New( &bitmap );
-
-      err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
-      if ( !err )
+      /* we convert to a single bitmap format for computing the checksum */
+      if ( !error )
       {
-        MD5_CTX        ctx;
-        unsigned char  md5[16];
-        int            i;
+        FT_Bitmap  bitmap;
+        FT_Error   err;
 
 
-        MD5_Init( &ctx);
-        MD5_Update( &ctx, bitmap.buffer, bitmap.rows * bitmap.pitch );
-        MD5_Final( md5, &ctx );
+        FT_Bitmap_Init( &bitmap );
 
-        FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
-                    "  ",
-                    bitmap.rows, bitmap.pitch ));
-        for ( i = 0; i < 16; i++ )
-          FT_TRACE3(( "%02X", md5[i] ));
-        FT_TRACE3(( "\n" ));
+        /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
+        err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
+        if ( !err )
+        {
+          MD5_CTX        ctx;
+          unsigned char  md5[16];
+          int            i;
+          unsigned int   rows  = bitmap.rows;
+          unsigned int   pitch = (unsigned int)bitmap.pitch;
+
+
+          MD5_Init( &ctx );
+          if ( bitmap.buffer )
+            MD5_Update( &ctx, bitmap.buffer, rows * pitch );
+          MD5_Final( md5, &ctx );
+
+          FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
+                      "  ",
+                      rows, pitch ));
+          for ( i = 0; i < 16; i++ )
+            FT_TRACE3(( "%02X", md5[i] ));
+          FT_TRACE3(( "\n" ));
+        }
+
+        FT_Bitmap_Done( library, &bitmap );
       }
-
-      FT_Bitmap_Done( library, &bitmap );
     }
 
 #undef  FT_COMPONENT
@@ -4194,7 +4314,7 @@
 
 
     if ( library && library->auto_hinter == module )
-      library->auto_hinter = 0;
+      library->auto_hinter = NULL;
 
     /* if the module is a renderer */
     if ( FT_MODULE_IS_RENDERER( module ) )
@@ -4221,7 +4341,7 @@
   {
     FT_Error   error;
     FT_Memory  memory;
-    FT_Module  module;
+    FT_Module  module = NULL;
     FT_UInt    nn;
 
 
@@ -4290,17 +4410,10 @@
     /* if the module is a font driver */
     if ( FT_MODULE_IS_DRIVER( module ) )
     {
-      /* allocate glyph loader if needed */
       FT_Driver  driver = FT_DRIVER( module );
 
 
       driver->clazz = (FT_Driver_Class)module->clazz;
-      if ( FT_DRIVER_USES_OUTLINES( driver ) )
-      {
-        error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
-        if ( error )
-          goto Fail;
-      }
     }
 
     if ( clazz->module_init )
@@ -4317,15 +4430,6 @@
     return error;
 
   Fail:
-    if ( FT_MODULE_IS_DRIVER( module ) )
-    {
-      FT_Driver  driver = FT_DRIVER( module );
-
-
-      if ( FT_DRIVER_USES_OUTLINES( driver ) )
-        FT_GlyphLoader_Done( driver->glyph_loader );
-    }
-
     if ( FT_MODULE_IS_RENDERER( module ) )
     {
       FT_Renderer  renderer = FT_RENDERER( module );
@@ -4348,7 +4452,7 @@
   FT_Get_Module( FT_Library   library,
                  const char*  module_name )
   {
-    FT_Module   result = 0;
+    FT_Module   result = NULL;
     FT_Module*  cur;
     FT_Module*  limit;
 
@@ -4460,7 +4564,7 @@
             cur[0] = cur[1];
             cur++;
           }
-          limit[0] = 0;
+          limit[0] = NULL;
 
           /* destroy the module */
           Destroy_Module( module );
@@ -4478,7 +4582,8 @@
                   const FT_String*  module_name,
                   const FT_String*  property_name,
                   void*             value,
-                  FT_Bool           set )
+                  FT_Bool           set,
+                  FT_Bool           value_is_string )
   {
     FT_Module*           cur;
     FT_Module*           limit;
@@ -4548,8 +4653,13 @@
       return FT_THROW( Unimplemented_Feature );
     }
 
-    return set ? service->set_property( cur[0], property_name, value )
-               : service->get_property( cur[0], property_name, value );
+    return set ? service->set_property( cur[0],
+                                        property_name,
+                                        value,
+                                        value_is_string )
+               : service->get_property( cur[0],
+                                        property_name,
+                                        value );
   }
 
 
@@ -4565,7 +4675,8 @@
                            module_name,
                            property_name,
                            (void*)value,
-                           TRUE );
+                           TRUE,
+                           FALSE );
   }
 
 
@@ -4581,10 +4692,33 @@
                            module_name,
                            property_name,
                            value,
+                           FALSE,
                            FALSE );
   }
 
 
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+
+  /* this variant is used for handling the FREETYPE_PROPERTIES */
+  /* environment variable                                      */
+
+  FT_BASE_DEF( FT_Error )
+  ft_property_string_set( FT_Library        library,
+                          const FT_String*  module_name,
+                          const FT_String*  property_name,
+                          FT_String*        value )
+  {
+    return ft_property_do( library,
+                           module_name,
+                           property_name,
+                           (void*)value,
+                           TRUE,
+                           TRUE );
+  }
+
+#endif
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -4603,6 +4737,9 @@
   FT_EXPORT_DEF( FT_Error )
   FT_Reference_Library( FT_Library  library )
   {
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
     library->refcount++;
 
     return FT_Err_Ok;
@@ -4619,7 +4756,7 @@
     FT_Error    error;
 
 
-    if ( !memory )
+    if ( !memory || !alibrary )
       return FT_THROW( Invalid_Argument );
 
 #ifdef FT_DEBUG_LEVEL_ERROR
@@ -4640,12 +4777,9 @@
       goto Fail;
 #endif
 
-    /* allocate the render pool */
-    library->raster_pool_size = FT_RENDER_POOL_SIZE;
-#if FT_RENDER_POOL_SIZE > 0
-    if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
-      goto Fail;
-#endif
+    /* we don't use raster_pool anymore. */
+    library->raster_pool_size = 0;
+    library->raster_pool      = NULL;
 
     library->version_major = FREETYPE_MAJOR;
     library->version_minor = FREETYPE_MINOR;
@@ -4658,8 +4792,8 @@
 
     return FT_Err_Ok;
 
-  Fail:
 #ifdef FT_CONFIG_OPTION_PIC
+  Fail:
     ft_pic_container_destroy( library );
 #endif
     FT_FREE( library );
@@ -4788,16 +4922,12 @@
         if ( module )
         {
           Destroy_Module( module );
-          library->modules[n] = 0;
+          library->modules[n] = NULL;
         }
       }
     }
 #endif
 
-    /* Destroy raster objects */
-    FT_FREE( library->raster_pool );
-    library->raster_pool_size = 0;
-
 #ifdef FT_CONFIG_OPTION_PIC
     /* Destroy pic container contents */
     ft_pic_container_destroy( library );
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 4a39dcd..fc28225 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType outline management (body).                                  */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010, 2012-2014 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -42,7 +42,7 @@
 
 
   static
-  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
+  const FT_Outline  null_outline = { 0, 0, NULL, NULL, NULL, 0 };
 
 
   /* documentation is in ftoutln.h */
@@ -52,8 +52,9 @@
                         const FT_Outline_Funcs*  func_interface,
                         void*                    user )
   {
-#undef SCALED
-#define SCALED( x )  ( ( (x) << shift ) - delta )
+#undef  SCALED
+#define SCALED( x )  ( ( (x) < 0 ? -( -(x) << shift )             \
+                                 :  (  (x) << shift ) ) - delta )
 
     FT_Vector   v_last;
     FT_Vector   v_control;
@@ -73,7 +74,10 @@
     FT_Pos   delta;
 
 
-    if ( !outline || !func_interface )
+    if ( !outline )
+      return FT_THROW( Invalid_Outline );
+
+    if ( !func_interface )
       return FT_THROW( Invalid_Argument );
 
     shift = func_interface->shift;
@@ -276,7 +280,7 @@
       if ( error )
         goto Exit;
 
-      first = last + 1;
+      first = (FT_UInt)last + 1;
     }
 
     FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
@@ -317,7 +321,7 @@
          FT_NEW_ARRAY( anoutline->contours, numContours ) )
       goto Fail;
 
-    anoutline->n_points    = (FT_UShort)numPoints;
+    anoutline->n_points    = (FT_Short)numPoints;
     anoutline->n_contours  = (FT_Short)numContours;
     anoutline->flags      |= FT_OUTLINE_OWNER;
 
@@ -362,7 +366,7 @@
 
       /* empty glyph? */
       if ( n_points == 0 && n_contours == 0 )
-        return 0;
+        return FT_Err_Ok;
 
       /* check point and contour counts */
       if ( n_points <= 0 || n_contours <= 0 )
@@ -384,7 +388,7 @@
         goto Bad;
 
       /* XXX: check the tags array */
-      return 0;
+      return FT_Err_Ok;
     }
 
   Bad:
@@ -401,19 +405,24 @@
     FT_Int  is_owner;
 
 
-    if ( !source            || !target            ||
-         source->n_points   != target->n_points   ||
+    if ( !source || !target )
+      return FT_THROW( Invalid_Outline );
+
+    if ( source->n_points   != target->n_points   ||
          source->n_contours != target->n_contours )
       return FT_THROW( Invalid_Argument );
 
     if ( source == target )
       return FT_Err_Ok;
 
-    FT_ARRAY_COPY( target->points, source->points, source->n_points );
+    if ( source->n_points )
+    {
+      FT_ARRAY_COPY( target->points, source->points, source->n_points );
+      FT_ARRAY_COPY( target->tags,   source->tags,   source->n_points );
+    }
 
-    FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
-
-    FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
+    if ( source->n_contours )
+      FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
 
     /* copy all flags, except the `FT_OUTLINE_OWNER' one */
     is_owner      = target->flags & FT_OUTLINE_OWNER;
@@ -430,20 +439,21 @@
   FT_Outline_Done_Internal( FT_Memory    memory,
                             FT_Outline*  outline )
   {
-    if ( memory && outline )
-    {
-      if ( outline->flags & FT_OUTLINE_OWNER )
-      {
-        FT_FREE( outline->points   );
-        FT_FREE( outline->tags     );
-        FT_FREE( outline->contours );
-      }
-      *outline = null_outline;
+    if ( !outline )
+      return FT_THROW( Invalid_Outline );
 
-      return FT_Err_Ok;
-    }
-    else
+    if ( !memory )
       return FT_THROW( Invalid_Argument );
+
+    if ( outline->flags & FT_OUTLINE_OWNER )
+    {
+      FT_FREE( outline->points   );
+      FT_FREE( outline->tags     );
+      FT_FREE( outline->contours );
+    }
+    *outline = null_outline;
+
+    return FT_Err_Ok;
   }
 
 
@@ -606,7 +616,6 @@
                      FT_Raster_Params*  params )
   {
     FT_Error     error;
-    FT_Bool      update = FALSE;
     FT_Renderer  renderer;
     FT_ListNode  node;
 
@@ -614,7 +623,10 @@
     if ( !library )
       return FT_THROW( Invalid_Library_Handle );
 
-    if ( !outline || !params )
+    if ( !outline )
+      return FT_THROW( Invalid_Outline );
+
+    if ( !params )
       return FT_THROW( Invalid_Argument );
 
     renderer = library->cur_renderer;
@@ -637,14 +649,8 @@
       /* format                                                */
       renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
                                      &node );
-      update   = TRUE;
     }
 
-    /* if we changed the current renderer for the glyph image format */
-    /* we need to select it as the next current one                  */
-    if ( !error && update && renderer )
-      FT_Set_Renderer( library, renderer, 0, 0 );
-
     return error;
   }
 
@@ -662,7 +668,7 @@
     if ( !abitmap )
       return FT_THROW( Invalid_Argument );
 
-    /* other checks are delayed to FT_Outline_Render() */
+    /* other checks are delayed to `FT_Outline_Render' */
 
     params.target = abitmap;
     params.flags  = 0;
@@ -905,13 +911,12 @@
                          FT_Pos       ystrength )
   {
     FT_Vector*  points;
-    FT_Vector   v_prev, v_first, v_next, v_cur;
-    FT_Int      c, n, first;
+    FT_Int      c, first, last;
     FT_Int      orientation;
 
 
     if ( !outline )
-      return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Outline );
 
     xstrength /= 2;
     ystrength /= 2;
@@ -932,87 +937,98 @@
     first = 0;
     for ( c = 0; c < outline->n_contours; c++ )
     {
-      FT_Vector  in, out, shift;
-      FT_Fixed   l_in, l_out, l, q, d;
-      int        last = outline->contours[c];
+      FT_Vector  in, out, anchor, shift;
+      FT_Fixed   l_in, l_out, l_anchor = 0, l, q, d;
+      FT_Int     i, j, k;
 
 
-      v_first = points[first];
-      v_prev  = points[last];
-      v_cur   = v_first;
+      l_in = 0;
+      last = outline->contours[c];
 
-      /* compute incoming normalized vector */
-      in.x = v_cur.x - v_prev.x;
-      in.y = v_cur.y - v_prev.y;
-      l_in = FT_Vector_Length( &in );
-      if ( l_in )
+      /* pacify compiler */
+      in.x = in.y = anchor.x = anchor.y = 0;
+
+      /* Counter j cycles though the points; counter i advances only  */
+      /* when points are moved; anchor k marks the first moved point. */
+      for ( i = last, j = first, k = -1;
+            j != i && i != k;
+            j = j < last ? j + 1 : first )
       {
-        in.x = FT_DivFix( in.x, l_in );
-        in.y = FT_DivFix( in.y, l_in );
-      }
-
-      for ( n = first; n <= last; n++ )
-      {
-        if ( n < last )
-          v_next = points[n + 1];
-        else
-          v_next = v_first;
-
-        /* compute outgoing normalized vector */
-        out.x = v_next.x - v_cur.x;
-        out.y = v_next.y - v_cur.y;
-        l_out = FT_Vector_Length( &out );
-        if ( l_out )
+        if ( j != k )
         {
-          out.x = FT_DivFix( out.x, l_out );
-          out.y = FT_DivFix( out.y, l_out );
-        }
+          out.x = points[j].x - points[i].x;
+          out.y = points[j].y - points[i].y;
+          l_out = (FT_Fixed)FT_Vector_NormLen( &out );
 
-        d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
-
-        /* shift only if turn is less than ~160 degrees */
-        if ( d > -0xF000L )
-        {
-          d = d + 0x10000L;
-
-          /* shift components are aligned along lateral bisector */
-          /* and directed according to the outline orientation.  */
-          shift.x = in.y + out.y;
-          shift.y = in.x + out.x;
-
-          if ( orientation == FT_ORIENTATION_TRUETYPE )
-            shift.x = -shift.x;
-          else
-            shift.y = -shift.y;
-
-          /* restrict shift magnitude to better handle collapsing segments */
-          q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
-          if ( orientation == FT_ORIENTATION_TRUETYPE )
-            q = -q;
-
-          l = FT_MIN( l_in, l_out );
-
-          /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
-          if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
-            shift.x = FT_MulDiv( shift.x, xstrength, d );
-          else
-            shift.x = FT_MulDiv( shift.x, l, q );
-
-
-          if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
-            shift.y = FT_MulDiv( shift.y, ystrength, d );
-          else
-            shift.y = FT_MulDiv( shift.y, l, q );
+          if ( l_out == 0 )
+            continue;
         }
         else
-          shift.x = shift.y = 0;
+        {
+          out   = anchor;
+          l_out = l_anchor;
+        }
 
-        outline->points[n].x = v_cur.x + xstrength + shift.x;
-        outline->points[n].y = v_cur.y + ystrength + shift.y;
+        if ( l_in != 0 )
+        {
+          if ( k < 0 )
+          {
+            k        = i;
+            anchor   = in;
+            l_anchor = l_in;
+          }
 
-        in    = out;
-        l_in  = l_out;
-        v_cur = v_next;
+          d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
+
+          /* shift only if turn is less than ~160 degrees */
+          if ( d > -0xF000L )
+          {
+            d = d + 0x10000L;
+
+            /* shift components along lateral bisector in proper orientation */
+            shift.x = in.y + out.y;
+            shift.y = in.x + out.x;
+
+            if ( orientation == FT_ORIENTATION_TRUETYPE )
+              shift.x = -shift.x;
+            else
+              shift.y = -shift.y;
+
+            /* restrict shift magnitude to better handle collapsing segments */
+            q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
+            if ( orientation == FT_ORIENTATION_TRUETYPE )
+              q = -q;
+
+            l = FT_MIN( l_in, l_out );
+
+            /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
+            if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) )
+              shift.x = FT_MulDiv( shift.x, xstrength, d );
+            else
+              shift.x = FT_MulDiv( shift.x, l, q );
+
+
+            if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) )
+              shift.y = FT_MulDiv( shift.y, ystrength, d );
+            else
+              shift.y = FT_MulDiv( shift.y, l, q );
+          }
+          else
+            shift.x = shift.y = 0;
+
+          for ( ;
+                i != j;
+                i = i < last ? i + 1 : first )
+          {
+            points[i].x += xstrength + shift.x;
+            points[i].y += ystrength + shift.y;
+          }
+        }
+        else
+          i = j;
+
+        in   = out;
+        l_in = l_out;
       }
 
       first = last + 1;
@@ -1041,14 +1057,19 @@
     /* We use the nonzero winding rule to find the orientation.       */
     /* Since glyph outlines behave much more `regular' than arbitrary */
     /* cubic or quadratic curves, this test deals with the polygon    */
-    /* only which is spanned up by the control points.                */
+    /* only that is spanned up by the control points.                 */
 
     FT_Outline_Get_CBox( outline, &cbox );
 
-    xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
+    /* Handle collapsed outlines to avoid undefined FT_MSB. */
+    if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax )
+      return FT_ORIENTATION_NONE;
+
+    xshift = FT_MSB( (FT_UInt32)( FT_ABS( cbox.xMax ) |
+                                  FT_ABS( cbox.xMin ) ) ) - 14;
     xshift = FT_MAX( xshift, 0 );
 
-    yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
+    yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14;
     yshift = FT_MAX( yshift, 0 );
 
     points = outline->points;
@@ -1059,13 +1080,16 @@
       FT_Int  last = outline->contours[c];
 
 
-      v_prev = points[last];
+      v_prev.x = points[last].x >> xshift;
+      v_prev.y = points[last].y >> yshift;
 
       for ( n = first; n <= last; n++ )
       {
-        v_cur = points[n];
-        area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
-                ( ( v_cur.x + v_prev.x ) >> xshift );
+        v_cur.x = points[n].x >> xshift;
+        v_cur.y = points[n].y >> yshift;
+
+        area += ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x );
+
         v_prev = v_cur;
       }
 
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
index 82b42f0..4861be1 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -3,9 +3,10 @@
 /*  ftpatent.c                                                             */
 /*                                                                         */
 /*    FreeType API for checking patented TrueType bytecode instructions    */
-/*    (body).                                                              */
+/*    (body).  Obsolete, retained for backwards compatibility.             */
 /*                                                                         */
-/*  Copyright 2007, 2008, 2010 by David Turner.                            */
+/*  Copyright 2007-2016 by                                                 */
+/*  David Turner.                                                          */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -24,238 +25,14 @@
 #include FT_SERVICE_TRUETYPE_GLYF_H
 
 
-  static FT_Bool
-  _tt_check_patents_in_range( FT_Stream  stream,
-                              FT_ULong   size )
-  {
-    FT_Bool   result = FALSE;
-    FT_Error  error;
-    FT_Bytes  p, end;
-
-
-    if ( FT_FRAME_ENTER( size ) )
-      return 0;
-
-    p   = stream->cursor;
-    end = p + size;
-
-    while ( p < end )
-    {
-      switch (p[0])
-      {
-      case 0x06:  /* SPvTL // */
-      case 0x07:  /* SPvTL +  */
-      case 0x08:  /* SFvTL // */
-      case 0x09:  /* SFvTL +  */
-      case 0x0A:  /* SPvFS    */
-      case 0x0B:  /* SFvFS    */
-        result = TRUE;
-        goto Exit;
-
-      case 0x40:
-        if ( p + 1 >= end )
-          goto Exit;
-
-        p += p[1] + 2;
-        break;
-
-      case 0x41:
-        if ( p + 1 >= end )
-          goto Exit;
-
-        p += p[1] * 2 + 2;
-        break;
-
-      case 0x71:  /* DELTAP2 */
-      case 0x72:  /* DELTAP3 */
-      case 0x73:  /* DELTAC0 */
-      case 0x74:  /* DELTAC1 */
-      case 0x75:  /* DELTAC2 */
-        result = TRUE;
-        goto Exit;
-
-      case 0xB0:
-      case 0xB1:
-      case 0xB2:
-      case 0xB3:
-      case 0xB4:
-      case 0xB5:
-      case 0xB6:
-      case 0xB7:
-        p += ( p[0] - 0xB0 ) + 2;
-        break;
-
-      case 0xB8:
-      case 0xB9:
-      case 0xBA:
-      case 0xBB:
-      case 0xBC:
-      case 0xBD:
-      case 0xBE:
-      case 0xBF:
-        p += ( p[0] - 0xB8 ) * 2 + 3;
-        break;
-
-      default:
-        p += 1;
-        break;
-      }
-    }
-
-  Exit:
-    FT_UNUSED( error );
-    FT_FRAME_EXIT();
-    return result;
-  }
-
-
-  static FT_Bool
-  _tt_check_patents_in_table( FT_Face   face,
-                              FT_ULong  tag )
-  {
-    FT_Stream              stream = face->stream;
-    FT_Error               error  = FT_Err_Ok;
-    FT_Service_SFNT_Table  service;
-    FT_Bool                result = FALSE;
-
-
-    FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
-
-    if ( service )
-    {
-      FT_UInt   i = 0;
-      FT_ULong  tag_i = 0, offset_i = 0, length_i = 0;
-
-
-      for ( i = 0; !error && tag_i != tag ; i++ )
-        error = service->table_info( face, i,
-                                     &tag_i, &offset_i, &length_i );
-
-      if ( error                      ||
-           FT_STREAM_SEEK( offset_i ) )
-        goto Exit;
-
-      result = _tt_check_patents_in_range( stream, length_i );
-    }
-
-  Exit:
-    return result;
-  }
-
-
-  static FT_Bool
-  _tt_face_check_patents( FT_Face  face )
-  {
-    FT_Stream  stream = face->stream;
-    FT_UInt    gindex;
-    FT_Error   error;
-    FT_Bool    result;
-
-    FT_Service_TTGlyf  service;
-
-
-    result = _tt_check_patents_in_table( face, TTAG_fpgm );
-    if ( result )
-      goto Exit;
-
-    result = _tt_check_patents_in_table( face, TTAG_prep );
-    if ( result )
-      goto Exit;
-
-    FT_FACE_FIND_SERVICE( face, service, TT_GLYF );
-    if ( service == NULL )
-      goto Exit;
-
-    for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ )
-    {
-      FT_ULong  offset, num_ins, size;
-      FT_Int    num_contours;
-
-
-      offset = service->get_location( face, gindex, &size );
-      if ( size == 0 )
-        continue;
-
-      if ( FT_STREAM_SEEK( offset )      ||
-           FT_READ_SHORT( num_contours ) )
-        continue;
-
-      if ( num_contours >= 0 )  /* simple glyph */
-      {
-        if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) )
-          continue;
-      }
-      else  /* compound glyph */
-      {
-        FT_Bool  has_instr = 0;
-
-
-        if ( FT_STREAM_SKIP( 8 ) )
-          continue;
-
-        /* now read each component */
-        for (;;)
-        {
-          FT_UInt  flags, toskip;
-
-
-          if( FT_READ_USHORT( flags ) )
-            break;
-
-          toskip = 2 + 1 + 1;
-
-          if ( ( flags & ( 1 << 0 ) ) != 0 )       /* ARGS_ARE_WORDS */
-            toskip += 2;
-
-          if ( ( flags & ( 1 << 3 ) ) != 0 )       /* WE_HAVE_A_SCALE */
-            toskip += 2;
-          else if ( ( flags & ( 1 << 6 ) ) != 0 )  /* WE_HAVE_X_Y_SCALE */
-            toskip += 4;
-          else if ( ( flags & ( 1 << 7 ) ) != 0 )  /* WE_HAVE_A_2x2 */
-            toskip += 8;
-
-          if ( ( flags & ( 1 << 8 ) ) != 0 )       /* WE_HAVE_INSTRUCTIONS */
-            has_instr = 1;
-
-          if ( FT_STREAM_SKIP( toskip ) )
-            goto NextGlyph;
-
-          if ( ( flags & ( 1 << 5 ) ) == 0 )       /* MORE_COMPONENTS */
-            break;
-        }
-
-        if ( !has_instr )
-          goto NextGlyph;
-      }
-
-      if ( FT_READ_USHORT( num_ins ) )
-        continue;
-
-      result = _tt_check_patents_in_range( stream, num_ins );
-      if ( result )
-        goto Exit;
-
-    NextGlyph:
-      ;
-    }
-
-  Exit:
-    return result;
-  }
-
-
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Bool )
   FT_Face_CheckTrueTypePatents( FT_Face  face )
   {
-    FT_Bool  result = FALSE;
+    FT_UNUSED( face );
 
-
-    if ( face && FT_IS_SFNT( face ) )
-      result = _tt_face_check_patents( face );
-
-    return result;
+    return FALSE;
   }
 
 
@@ -265,22 +42,10 @@
   FT_Face_SetUnpatentedHinting( FT_Face  face,
                                 FT_Bool  value )
   {
-    FT_Bool  result = FALSE;
-
-
-#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
-    !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
-    if ( face && FT_IS_SFNT( face ) )
-    {
-      result = !face->internal->ignore_unpatented_hinter;
-      face->internal->ignore_unpatented_hinter = !value;
-    }
-#else
     FT_UNUSED( face );
     FT_UNUSED( value );
-#endif
 
-    return result;
+    return FALSE;
   }
 
 /* END */
diff --git a/src/base/ftpic.c b/src/base/ftpic.c
index 9bd92f7..03769db 100644
--- a/src/base/ftpic.c
+++ b/src/base/ftpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services (body).              */
 /*                                                                         */
-/*  Copyright 2009, 2013 by                                                */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 5352970..4660c97 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (body).                             */
 /*                                                                         */
-/*  Copyright 2004-2010, 2013, 2014 by                                     */
+/*  Copyright 2004-2016 by                                                 */
 /*  Masatake YAMATO and Redhat K.K.                                        */
 /*                                                                         */
 /*  FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are     */
@@ -63,7 +63,7 @@
     FT_UNUSED( library );
 
 
-    error = FT_Stream_Seek( stream, rfork_offset );
+    error = FT_Stream_Seek( stream, (FT_ULong)rfork_offset );
     if ( error )
       return error;
 
@@ -71,25 +71,36 @@
     if ( error )
       return error;
 
-    *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
-                                  ( head[1] << 16 ) |
-                                  ( head[2] <<  8 ) |
-                                    head[3]         );
-    map_pos    = rfork_offset + ( ( head[4] << 24 ) |
-                                  ( head[5] << 16 ) |
-                                  ( head[6] <<  8 ) |
-                                    head[7]         );
-    rdata_len = ( head[ 8] << 24 ) |
-                ( head[ 9] << 16 ) |
-                ( head[10] <<  8 ) |
-                  head[11];
+    /* ensure positive values */
+    if ( head[0] >= 0x80 || head[4] >= 0x80 || head[8] >= 0x80 )
+      return FT_THROW( Unknown_File_Format );
+
+    *rdata_pos = ( head[ 0] << 24 ) |
+                 ( head[ 1] << 16 ) |
+                 ( head[ 2] <<  8 ) |
+                   head[ 3];
+    map_pos    = ( head[ 4] << 24 ) |
+                 ( head[ 5] << 16 ) |
+                 ( head[ 6] <<  8 ) |
+                   head[ 7];
+    rdata_len  = ( head[ 8] << 24 ) |
+                 ( head[ 9] << 16 ) |
+                 ( head[10] <<  8 ) |
+                   head[11];
 
     /* map_len = head[12] .. head[15] */
 
-    if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
+    if ( *rdata_pos != map_pos - rdata_len || map_pos == 0 )
       return FT_THROW( Unknown_File_Format );
 
-    error = FT_Stream_Seek( stream, map_pos );
+    if ( FT_LONG_MAX - rfork_offset < *rdata_pos ||
+         FT_LONG_MAX - rfork_offset < map_pos    )
+      return FT_THROW( Unknown_File_Format );
+
+    *rdata_pos += rfork_offset;
+    map_pos    += rfork_offset;
+
+    error = FT_Stream_Seek( stream, (FT_ULong)map_pos );
     if ( error )
       return error;
 
@@ -124,7 +135,7 @@
     if ( type_list == -1 )
       return FT_THROW( Unknown_File_Format );
 
-    error = FT_Stream_Seek( stream, map_pos + type_list );
+    error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) );
     if ( error )
       return error;
 
@@ -166,7 +177,7 @@
 
 
     FT_TRACE3(( "\n" ));
-    error = FT_Stream_Seek( stream, map_offset );
+    error = FT_Stream_Seek( stream, (FT_ULong)map_offset );
     if ( error )
       return error;
 
@@ -182,10 +193,10 @@
         return error;
 
       FT_TRACE2(( "Resource tags: %c%c%c%c\n",
-                  (char)( 0xff & ( tag_internal >> 24 ) ),
-                  (char)( 0xff & ( tag_internal >> 16 ) ),
-                  (char)( 0xff & ( tag_internal >>  8 ) ),
-                  (char)( 0xff & ( tag_internal >>  0 ) ) ));
+                  (char)( 0xFF & ( tag_internal >> 24 ) ),
+                  (char)( 0xFF & ( tag_internal >> 16 ) ),
+                  (char)( 0xFF & ( tag_internal >>  8 ) ),
+                  (char)( 0xFF & ( tag_internal >>  0 ) ) ));
       FT_TRACE3(( "             : subcount=%d, suboffset=0x%04x\n",
                   subcnt, rpos ));
 
@@ -194,7 +205,7 @@
         *count = subcnt + 1;
         rpos  += map_offset;
 
-        error = FT_Stream_Seek( stream, rpos );
+        error = FT_Stream_Seek( stream, (FT_ULong)rpos );
         if ( error )
           return error;
 
@@ -220,7 +231,7 @@
 
         if (sort_by_res_id)
         {
-          ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
+          ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ),
                     ( int(*)(const void*, const void*) )
                     ft_raccess_sort_ref_by_id );
 
@@ -392,7 +403,7 @@
         errors[i] = FT_Err_Ok;
 
       if ( errors[i] )
-        continue ;
+        continue;
 
       errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
                                                  stream, base_name,
@@ -713,9 +724,9 @@
     FT_UShort  n_of_entries;
 
     int        i;
-    FT_UInt32  entry_id, entry_offset, entry_length = 0;
+    FT_Int32   entry_id, entry_offset, entry_length = 0;
 
-    const FT_UInt32  resource_fork_entry_id = 0x2;
+    const FT_Int32  resource_fork_entry_id = 0x2;
 
     FT_UNUSED( library );
     FT_UNUSED( base_file_name );
@@ -813,7 +824,9 @@
     tmp = ft_strrchr( original_name, '/' );
     if ( tmp )
     {
-      ft_strncpy( new_name, original_name, tmp - original_name + 1 );
+      ft_strncpy( new_name,
+                  original_name,
+                  (size_t)( tmp - original_name + 1 ) );
       new_name[tmp - original_name + 1] = '\0';
       slash = tmp + 1;
     }
diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c
index 260e91c..ce79641 100644
--- a/src/base/ftsnames.c
+++ b/src/base/ftsnames.c
@@ -7,7 +7,7 @@
 /*                                                                         */
 /*    This is _not_ used to retrieve glyph names!                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2009 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index d965333..bb512a7 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    I/O stream support (body).                                           */
 /*                                                                         */
-/*  Copyright 2000-2002, 2004-2006, 2008-2011, 2013 by                     */
+/*  Copyright 2000-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -39,9 +39,9 @@
     stream->base   = (FT_Byte*) base;
     stream->size   = size;
     stream->pos    = 0;
-    stream->cursor = 0;
-    stream->read   = 0;
-    stream->close  = 0;
+    stream->cursor = NULL;
+    stream->read   = NULL;
+    stream->close  = NULL;
   }
 
 
@@ -95,11 +95,11 @@
     if ( distance < 0 )
       return FT_THROW( Invalid_Stream_Operation );
 
-    return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
+    return FT_Stream_Seek( stream, stream->pos + (FT_ULong)distance );
   }
 
 
-  FT_BASE_DEF( FT_Long )
+  FT_BASE_DEF( FT_ULong )
   FT_Stream_Pos( FT_Stream  stream )
   {
     return stream->pos;
@@ -203,8 +203,8 @@
       *pbytes = (FT_Byte*)stream->cursor;
 
       /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
-      stream->cursor = 0;
-      stream->limit  = 0;
+      stream->cursor = NULL;
+      stream->limit  = NULL;
     }
 
     return error;
@@ -226,7 +226,7 @@
       FT_FREE( *pbytes );
 #endif
     }
-    *pbytes = 0;
+    *pbytes = NULL;
   }
 
 
@@ -260,7 +260,9 @@
 
 #ifdef FT_DEBUG_MEMORY
       /* assume _ft_debug_file and _ft_debug_lineno are already set */
-      stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
+      stream->base = (unsigned char*)ft_mem_qalloc( memory,
+                                                    (FT_Long)count,
+                                                    &error );
       if ( error )
         goto Exit;
 #else
@@ -333,8 +335,8 @@
       FT_FREE( stream->base );
 #endif
     }
-    stream->cursor = 0;
-    stream->limit  = 0;
+    stream->cursor = NULL;
+    stream->limit  = NULL;
   }
 
 
@@ -348,7 +350,7 @@
 
     result = 0;
     if ( stream->cursor < stream->limit )
-      result = *stream->cursor++;
+      result = (FT_Char)*stream->cursor++;
 
     return result;
   }
@@ -357,8 +359,8 @@
   FT_BASE_DEF( FT_UShort )
   FT_Stream_GetUShort( FT_Stream  stream )
   {
-    FT_Byte*  p;
-    FT_Short  result;
+    FT_Byte*   p;
+    FT_UShort  result;
 
 
     FT_ASSERT( stream && stream->cursor );
@@ -376,8 +378,8 @@
   FT_BASE_DEF( FT_UShort )
   FT_Stream_GetUShortLE( FT_Stream  stream )
   {
-    FT_Byte*  p;
-    FT_Short  result;
+    FT_Byte*   p;
+    FT_UShort  result;
 
 
     FT_ASSERT( stream && stream->cursor );
@@ -396,7 +398,7 @@
   FT_Stream_GetUOffset( FT_Stream  stream )
   {
     FT_Byte*  p;
-    FT_Long   result;
+    FT_ULong  result;
 
 
     FT_ASSERT( stream && stream->cursor );
@@ -414,7 +416,7 @@
   FT_Stream_GetULong( FT_Stream  stream )
   {
     FT_Byte*  p;
-    FT_Long   result;
+    FT_ULong  result;
 
 
     FT_ASSERT( stream && stream->cursor );
@@ -432,7 +434,7 @@
   FT_Stream_GetULongLE( FT_Stream  stream )
   {
     FT_Byte*  p;
-    FT_Long   result;
+    FT_ULong  result;
 
 
     FT_ASSERT( stream && stream->cursor );
@@ -471,7 +473,7 @@
     }
     stream->pos++;
 
-    return result;
+    return (FT_Char)result;
 
   Fail:
     *error = FT_THROW( Invalid_Stream_Operation );
@@ -485,11 +487,11 @@
 
   FT_BASE_DEF( FT_UShort )
   FT_Stream_ReadUShort( FT_Stream  stream,
-                       FT_Error*  error )
+                        FT_Error*  error )
   {
-    FT_Byte   reads[2];
-    FT_Byte*  p = 0;
-    FT_Short  result = 0;
+    FT_Byte    reads[2];
+    FT_Byte*   p      = 0;
+    FT_UShort  result = 0;
 
 
     FT_ASSERT( stream );
@@ -506,9 +508,7 @@
         p = reads;
       }
       else
-      {
         p = stream->base + stream->pos;
-      }
 
       if ( p )
         result = FT_NEXT_USHORT( p );
@@ -532,11 +532,11 @@
 
   FT_BASE_DEF( FT_UShort )
   FT_Stream_ReadUShortLE( FT_Stream  stream,
-                         FT_Error*  error )
+                          FT_Error*  error )
   {
-    FT_Byte   reads[2];
-    FT_Byte*  p = 0;
-    FT_Short  result = 0;
+    FT_Byte    reads[2];
+    FT_Byte*   p      = 0;
+    FT_UShort  result = 0;
 
 
     FT_ASSERT( stream );
@@ -553,9 +553,7 @@
         p = reads;
       }
       else
-      {
         p = stream->base + stream->pos;
-      }
 
       if ( p )
         result = FT_NEXT_USHORT_LE( p );
@@ -579,11 +577,11 @@
 
   FT_BASE_DEF( FT_ULong )
   FT_Stream_ReadUOffset( FT_Stream  stream,
-                        FT_Error*  error )
+                         FT_Error*  error )
   {
     FT_Byte   reads[3];
-    FT_Byte*  p = 0;
-    FT_Long   result = 0;
+    FT_Byte*  p      = 0;
+    FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
@@ -600,9 +598,7 @@
         p = reads;
       }
       else
-      {
         p = stream->base + stream->pos;
-      }
 
       if ( p )
         result = FT_NEXT_UOFF3( p );
@@ -626,11 +622,11 @@
 
   FT_BASE_DEF( FT_ULong )
   FT_Stream_ReadULong( FT_Stream  stream,
-                      FT_Error*  error )
+                       FT_Error*  error )
   {
     FT_Byte   reads[4];
-    FT_Byte*  p = 0;
-    FT_Long   result = 0;
+    FT_Byte*  p      = 0;
+    FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
@@ -647,9 +643,7 @@
         p = reads;
       }
       else
-      {
         p = stream->base + stream->pos;
-      }
 
       if ( p )
         result = FT_NEXT_ULONG( p );
@@ -673,11 +667,11 @@
 
   FT_BASE_DEF( FT_ULong )
   FT_Stream_ReadULongLE( FT_Stream  stream,
-                        FT_Error*  error )
+                         FT_Error*  error )
   {
     FT_Byte   reads[4];
-    FT_Byte*  p = 0;
-    FT_Long   result = 0;
+    FT_Byte*  p      = 0;
+    FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
@@ -694,9 +688,7 @@
         p = reads;
       }
       else
-      {
         p = stream->base + stream->pos;
-      }
 
       if ( p )
         result = FT_NEXT_ULONG_LE( p );
@@ -728,9 +720,12 @@
     FT_Byte*  cursor;
 
 
-    if ( !fields || !stream )
+    if ( !fields )
       return FT_THROW( Invalid_Argument );
 
+    if ( !stream )
+      return FT_THROW( Invalid_Stream_Handle );
+
     cursor = stream->cursor;
 
     error = FT_Err_Ok;
@@ -783,7 +778,7 @@
 
       case ft_frame_short_be:
       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
-        value = FT_NEXT_USHORT( cursor) ;
+        value = FT_NEXT_USHORT( cursor );
         sign_shift = 16;
         break;
 
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index ee61cec..4f3c493 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002-2006, 2008-2011, 2013 by                                */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,6 +24,16 @@
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 
+#include "basepic.h"
+
+
+  /* declare an extern to access `ft_outline_glyph_class' globally     */
+  /* allocated  in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
+  /* macro to access it when FT_CONFIG_OPTION_PIC is defined           */
+#ifndef FT_CONFIG_OPTION_PIC
+  FT_CALLBACK_TABLE const FT_Glyph_Class  ft_outline_glyph_class;
+#endif
+
 
   /* documentation is in ftstroke.h */
 
@@ -347,7 +357,7 @@
   ft_stroke_border_close( FT_StrokeBorder  border,
                           FT_Bool          reverse )
   {
-    FT_UInt  start = border->start;
+    FT_UInt  start = (FT_UInt)border->start;
     FT_UInt  count = border->num_points;
 
 
@@ -599,7 +609,7 @@
     if ( border->start >= 0 )
       ft_stroke_border_close( border, FALSE );
 
-    border->start = border->num_points;
+    border->start = (FT_Int)border->num_points;
     border->movable = FALSE;
 
     return ft_stroke_border_lineto( border, to, FALSE );
@@ -702,9 +712,10 @@
                            FT_Outline*      outline )
   {
     /* copy point locations */
-    FT_ARRAY_COPY( outline->points + outline->n_points,
-                   border->points,
-                   border->num_points );
+    if ( border->num_points )
+      FT_ARRAY_COPY( outline->points + outline->n_points,
+                     border->points,
+                     border->num_points );
 
     /* copy tags */
     {
@@ -742,7 +753,7 @@
       }
     }
 
-    outline->n_points = (short)( outline->n_points + border->num_points );
+    outline->n_points += (short)border->num_points;
 
     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
   }
@@ -795,6 +806,9 @@
 
 
     if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
+    if ( !astroker )
       return FT_THROW( Invalid_Argument );
 
     memory = library->memory;
@@ -822,14 +836,17 @@
                   FT_Stroker_LineJoin  line_join,
                   FT_Fixed             miter_limit )
   {
+    if ( !stroker )
+      return;
+
     stroker->radius      = radius;
     stroker->line_cap    = line_cap;
     stroker->line_join   = line_join;
     stroker->miter_limit = miter_limit;
 
     /* ensure miter limit has sensible value */
-    if ( stroker->miter_limit < 0x10000 )
-      stroker->miter_limit = 0x10000;
+    if ( stroker->miter_limit < 0x10000L )
+      stroker->miter_limit = 0x10000L;
 
     /* save line join style:                                           */
     /* line join style can be temporarily changed when stroking curves */
@@ -993,7 +1010,9 @@
 
     /* Only intersect borders if between two lineto's and both */
     /* lines are long enough (line_length is zero for curves). */
-    if ( !border->movable || line_length == 0 )
+    /* Also avoid U-turns of nearly 180 degree.                */
+    if ( !border->movable || line_length == 0  ||
+         theta > 0x59C000 || theta < -0x59C000 )
       intersect = FALSE;
     else
     {
@@ -1002,7 +1021,8 @@
                                                     FT_Tan( theta ) ) );
 
 
-      intersect = FT_BOOL( stroker->line_length >= min_length &&
+      intersect = FT_BOOL( min_length                         &&
+                           stroker->line_length >= min_length &&
                            line_length          >= min_length );
     }
 
@@ -1213,11 +1233,8 @@
       goto Exit;
 
     /* when we turn to the right, the inside side is 0 */
-    inside_side = 0;
-
     /* otherwise, the inside side is 1 */
-    if ( turn < 0 )
-      inside_side = 1;
+    inside_side = ( turn < 0 );
 
     /* process the inside side */
     error = ft_stroker_inside( stroker, inside_side, line_length );
@@ -1225,7 +1242,7 @@
       goto Exit;
 
     /* process the outside side */
-    error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
+    error = ft_stroker_outside( stroker, !inside_side, line_length );
 
   Exit:
     return error;
@@ -1287,6 +1304,9 @@
     FT_Fixed         line_length;
 
 
+    if ( !stroker || !to )
+      return FT_THROW( Invalid_Argument );
+
     delta.x = to->x - stroker->center.x;
     delta.y = to->y - stroker->center.y;
 
@@ -1360,6 +1380,12 @@
     FT_Bool     first_arc = TRUE;
 
 
+    if ( !stroker || !control || !to )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
     /* if all control points are coincident, this is a no-op; */
     /* avoid creating a spurious corner                       */
     if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
@@ -1556,6 +1582,12 @@
     FT_Bool     first_arc = TRUE;
 
 
+    if ( !stroker || !control1 || !control2 || !to )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
     /* if all control points are coincident, this is a no-op; */
     /* avoid creating a spurious corner */
     if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
@@ -1758,6 +1790,9 @@
                            FT_Vector*  to,
                            FT_Bool     open )
   {
+    if ( !stroker || !to )
+      return FT_THROW( Invalid_Argument );
+
     /* We cannot process the first point, because there is not enough      */
     /* information regarding its corner/cap.  The latter will be processed */
     /* in the `FT_Stroker_EndSubPath' routine.                             */
@@ -1797,7 +1832,7 @@
 
     FT_ASSERT( left->start >= 0 );
 
-    new_points = left->num_points - left->start;
+    new_points = (FT_Int)left->num_points - left->start;
     if ( new_points > 0 )
     {
       error = ft_stroke_border_grow( right, (FT_UInt)new_points );
@@ -1837,8 +1872,8 @@
         }
       }
 
-      left->num_points   = left->start;
-      right->num_points += new_points;
+      left->num_points   = (FT_UInt)left->start;
+      right->num_points += (FT_UInt)new_points;
 
       right->movable = FALSE;
       left->movable  = FALSE;
@@ -1858,6 +1893,12 @@
     FT_Error  error = FT_Err_Ok;
 
 
+    if ( !stroker )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
     if ( stroker->subpath_open )
     {
       FT_StrokeBorder  right = stroker->borders;
@@ -1910,11 +1951,8 @@
       if ( turn != 0 )
       {
         /* when we turn to the right, the inside side is 0 */
-        inside_side = 0;
-
         /* otherwise, the inside side is 1 */
-        if ( turn < 0 )
-          inside_side = 1;
+        inside_side = ( turn < 0 );
 
         error = ft_stroker_inside( stroker,
                                    inside_side,
@@ -1924,7 +1962,7 @@
 
         /* process the outside side */
         error = ft_stroker_outside( stroker,
-                                    1 - inside_side,
+                                    !inside_side,
                                     stroker->subpath_line_length );
         if ( error )
           goto Exit;
@@ -1983,6 +2021,12 @@
     FT_Error  error;
 
 
+    if ( !stroker )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
     error = ft_stroke_border_get_counts( stroker->borders + 0,
                                          &count1, &count2 );
     if ( error )
@@ -1997,8 +2041,12 @@
     num_contours = count2 + count4;
 
   Exit:
-    *anum_points   = num_points;
-    *anum_contours = num_contours;
+    if ( anum_points )
+      *anum_points   = num_points;
+
+    if ( anum_contours )
+      *anum_contours = num_contours;
+
     return error;
   }
 
@@ -2010,6 +2058,9 @@
                            FT_StrokerBorder  border,
                            FT_Outline*       outline )
   {
+    if ( !stroker || !outline )
+      return;
+
     if ( border == FT_STROKER_BORDER_LEFT  ||
          border == FT_STROKER_BORDER_RIGHT )
     {
@@ -2059,7 +2110,10 @@
     FT_Int      tag;       /* current point's state           */
 
 
-    if ( !outline || !stroker )
+    if ( !outline )
+      return FT_THROW( Invalid_Outline );
+
+    if ( !stroker )
       return FT_THROW( Invalid_Argument );
 
     FT_Stroker_Rewind( stroker );
@@ -2071,7 +2125,7 @@
       FT_UInt  last;  /* index of last point in contour */
 
 
-      last  = outline->contours[n];
+      last  = (FT_UInt)outline->contours[n];
       limit = outline->points + last;
 
       /* skip empty points; we don't stroke these */
@@ -2242,15 +2296,6 @@
   }
 
 
-  /* declare an extern to access `ft_outline_glyph_class' globally     */
-  /* allocated  in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
-  /* macro to access it when FT_CONFIG_OPTION_PIC is defined           */
-#ifndef FT_CONFIG_OPTION_PIC
-  extern const FT_Glyph_Class  ft_outline_glyph_class;
-#endif
-#include "basepic.h"
-
-
   /* documentation is in ftstroke.h */
 
   FT_EXPORT_DEF( FT_Error )
@@ -2258,18 +2303,20 @@
                    FT_Stroker   stroker,
                    FT_Bool      destroy )
   {
-    FT_Error    error   = FT_ERR( Invalid_Argument );
-    FT_Glyph    glyph   = NULL;
+    FT_Error  error = FT_ERR( Invalid_Argument );
+    FT_Glyph  glyph = NULL;
+
+    /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
     FT_Library  library = stroker->library;
 
     FT_UNUSED( library );
 
 
-    if ( pglyph == NULL )
+    if ( !pglyph )
       goto Exit;
 
     glyph = *pglyph;
-    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+    if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
       goto Exit;
 
     {
@@ -2293,12 +2340,14 @@
       if ( error )
         goto Fail;
 
-      (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
+      FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
 
       FT_Outline_Done( glyph->library, outline );
 
       error = FT_Outline_New( glyph->library,
-                              num_points, num_contours, outline );
+                              num_points,
+                              (FT_Int)num_contours,
+                              outline );
       if ( error )
         goto Fail;
 
@@ -2334,18 +2383,20 @@
                          FT_Bool      inside,
                          FT_Bool      destroy )
   {
-    FT_Error    error   = FT_ERR( Invalid_Argument );
-    FT_Glyph    glyph   = NULL;
+    FT_Error  error = FT_ERR( Invalid_Argument );
+    FT_Glyph  glyph = NULL;
+
+    /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
     FT_Library  library = stroker->library;
 
     FT_UNUSED( library );
 
 
-    if ( pglyph == NULL )
+    if ( !pglyph )
       goto Exit;
 
     glyph = *pglyph;
-    if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+    if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
       goto Exit;
 
     {
@@ -2379,14 +2430,14 @@
       if ( error )
         goto Fail;
 
-      (void)FT_Stroker_GetBorderCounts( stroker, border,
-                                        &num_points, &num_contours );
+      FT_Stroker_GetBorderCounts( stroker, border,
+                                  &num_points, &num_contours );
 
       FT_Outline_Done( glyph->library, outline );
 
       error = FT_Outline_New( glyph->library,
                               num_points,
-                              num_contours,
+                              (FT_Int)num_contours,
                               outline );
       if ( error )
         goto Fail;
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index 3098a60..4b66a33 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, 2013 by                               */
+/*  Copyright 2000-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -48,9 +48,14 @@
   FT_GlyphSlot_Oblique( FT_GlyphSlot  slot )
   {
     FT_Matrix    transform;
-    FT_Outline*  outline = &slot->outline;
+    FT_Outline*  outline;
 
 
+    if ( !slot )
+      return;
+
+    outline = &slot->outline;
+
     /* only oblique outline glyphs */
     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
       return;
@@ -84,12 +89,18 @@
   FT_EXPORT_DEF( void )
   FT_GlyphSlot_Embolden( FT_GlyphSlot  slot )
   {
-    FT_Library  library = slot->library;
-    FT_Face     face    = slot->face;
+    FT_Library  library;
+    FT_Face     face;
     FT_Error    error;
     FT_Pos      xstr, ystr;
 
 
+    if ( !slot )
+      return;
+
+    library = slot->library;
+    face    = slot->face;
+
     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
          slot->format != FT_GLYPH_FORMAT_BITMAP  )
       return;
@@ -100,10 +111,8 @@
     ystr = xstr;
 
     if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
-    {
-      /* ignore error */
-      (void)FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
-    }
+      FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
+
     else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
     {
       /* round to full pixels */
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 2c6ddac..ac1f01c 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific FreeType low-level system interface (body).            */
 /*                                                                         */
-/*  Copyright 1996-2002, 2006, 2008-2011, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -71,7 +71,7 @@
   {
     FT_UNUSED( memory );
 
-    return ft_smalloc( size );
+    return ft_smalloc( (size_t)size );
   }
 
 
@@ -104,7 +104,7 @@
     FT_UNUSED( memory );
     FT_UNUSED( cur_size );
 
-    return ft_srealloc( block, new_size );
+    return ft_srealloc( block, (size_t)new_size );
   }
 
 
@@ -171,7 +171,7 @@
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
@@ -212,7 +212,7 @@
     file = STREAM_FILE( stream );
 
     if ( stream->pos != offset )
-      ft_fseek( file, offset, SEEK_SET );
+      ft_fseek( file, (long)offset, SEEK_SET );
 
     return (unsigned long)ft_fread( buffer, 1, count, file );
   }
@@ -232,7 +232,7 @@
 
     stream->descriptor.pointer = NULL;
     stream->pathname.pointer   = (char*)filepathname;
-    stream->base               = 0;
+    stream->base               = NULL;
     stream->pos                = 0;
     stream->read               = NULL;
     stream->close              = NULL;
@@ -247,7 +247,7 @@
     }
 
     ft_fseek( file, 0, SEEK_END );
-    stream->size = ft_ftell( file );
+    stream->size = (unsigned long)ft_ftell( file );
     if ( !stream->size )
     {
       FT_ERROR(( "FT_Stream_Open:" ));
@@ -292,7 +292,7 @@
     memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
     if ( memory )
     {
-      memory->user    = 0;
+      memory->user    = NULL;
       memory->alloc   = ft_alloc;
       memory->realloc = ft_realloc;
       memory->free    = ft_free;
diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c
index 4ffdcb7..7b582c8 100644
--- a/src/base/fttrigon.c
+++ b/src/base/fttrigon.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (body).                             */
 /*                                                                         */
-/*  Copyright 2001-2005, 2012-2013 by                                      */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -45,7 +45,7 @@
   /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
 #define FT_TRIG_MAX_ITERS  23
 
-  static const FT_Fixed
+  static const FT_Angle
   ft_trig_arctan_table[] =
   {
     1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
@@ -60,17 +60,21 @@
   static FT_Fixed
   ft_trig_downscale( FT_Fixed  val )
   {
-    FT_Fixed  s;
-    FT_Int64  v;
+    FT_Int  s = 1;
 
 
-    s   = val;
-    val = FT_ABS( val );
+    if ( val < 0 )
+    {
+       val = -val;
+       s = -1;
+    }
 
-    v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
-    val = (FT_Fixed)( v >> 32 );
+    /* 0x40000000 comes from regression analysis between true */
+    /* and CORDIC hypotenuse, so it minimizes the error       */
+    val = (FT_Fixed)(
+            ( (FT_UInt64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
 
-    return ( s >= 0 ) ? val : -val;
+    return s < 0 ? -val : val;
   }
 
 #else /* !FT_LONG64 */
@@ -79,38 +83,53 @@
   static FT_Fixed
   ft_trig_downscale( FT_Fixed  val )
   {
-    FT_Fixed   s;
-    FT_UInt32  v1, v2, k1, k2, hi, lo1, lo2, lo3;
+    FT_Int     s = 1;
+    FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
 
 
-    s   = val;
-    val = FT_ABS( val );
+    if ( val < 0 )
+    {
+       val = -val;
+       s = -1;
+    }
 
-    v1 = (FT_UInt32)val >> 16;
-    v2 = (FT_UInt32)( val & 0xFFFFL );
+    lo1 = (FT_UInt32)val & 0x0000FFFFU;
+    hi1 = (FT_UInt32)val >> 16;
+    lo2 = FT_TRIG_SCALE & 0x0000FFFFU;
+    hi2 = FT_TRIG_SCALE >> 16;
 
-    k1 = (FT_UInt32)FT_TRIG_SCALE >> 16;           /* constant */
-    k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL );   /* constant */
+    lo = lo1 * lo2;
+    i1 = lo1 * hi2;
+    i2 = lo2 * hi1;
+    hi = hi1 * hi2;
 
-    hi   = k1 * v1;
-    lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
+    /* Check carry overflow of i1 + i2 */
+    i1 += i2;
+    hi += (FT_UInt32)( i1 < i2 ) << 16;
 
-    lo2  = ( k2 * v2 ) >> 16;
-    lo3  = FT_MAX( lo1, lo2 );
-    lo1 += lo2;
+    hi += i1 >> 16;
+    i1  = i1 << 16;
 
-    hi  += lo1 >> 16;
-    if ( lo1 < lo3 )
-      hi += (FT_UInt32)0x10000UL;
+    /* Check carry overflow of i1 + lo */
+    lo += i1;
+    hi += ( lo < i1 );
 
-    val  = (FT_Fixed)hi;
+    /* 0x40000000 comes from regression analysis between true */
+    /* and CORDIC hypotenuse, so it minimizes the error       */
 
-    return ( s >= 0 ) ? val : -val;
+    /* Check carry overflow of lo + 0x40000000 */
+    lo += 0x40000000UL;
+    hi += ( lo < 0x40000000UL );
+
+    val = (FT_Fixed)hi;
+
+    return s < 0 ? -val : val;
   }
 
 #endif /* !FT_LONG64 */
 
 
+  /* undefined and never called for zero vector */
   static FT_Int
   ft_trig_prenorm( FT_Vector*  vec )
   {
@@ -121,7 +140,7 @@
     x = vec->x;
     y = vec->y;
 
-    shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) );
+    shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) );
 
     if ( shift <= FT_TRIG_SAFE_MSB )
     {
@@ -147,7 +166,7 @@
   {
     FT_Int           i;
     FT_Fixed         x, y, xtemp, b;
-    const FT_Fixed  *arctanptr;
+    const FT_Angle  *arctanptr;
 
 
     x = vec->x;
@@ -202,7 +221,7 @@
     FT_Angle         theta;
     FT_Int           i;
     FT_Fixed         x, y, xtemp, b;
-    const FT_Fixed  *arctanptr;
+    const FT_Angle  *arctanptr;
 
 
     x = vec->x;
@@ -261,11 +280,12 @@
       }
     }
 
-    /* round theta */
+    /* round theta to acknowledge its error that mostly comes */
+    /* from accumulated rounding errors in the arctan table   */
     if ( theta >= 0 )
-      theta = FT_PAD_ROUND( theta, 32 );
+      theta = FT_PAD_ROUND( theta, 16 );
     else
-      theta = -FT_PAD_ROUND( -theta, 32 );
+      theta = -FT_PAD_ROUND( -theta, 16 );
 
     vec->x = x;
     vec->y = theta;
@@ -280,11 +300,9 @@
     FT_Vector  v;
 
 
-    v.x = FT_TRIG_SCALE >> 8;
-    v.y = 0;
-    ft_trig_pseudo_rotate( &v, angle );
+    FT_Vector_Unit( &v, angle );
 
-    return ( v.x + 0x80L ) >> 8;
+    return v.x;
   }
 
 
@@ -293,7 +311,12 @@
   FT_EXPORT_DEF( FT_Fixed )
   FT_Sin( FT_Angle  angle )
   {
-    return FT_Cos( FT_ANGLE_PI2 - angle );
+    FT_Vector  v;
+
+
+    FT_Vector_Unit( &v, angle );
+
+    return v.y;
   }
 
 
@@ -305,9 +328,7 @@
     FT_Vector  v;
 
 
-    v.x = FT_TRIG_SCALE >> 8;
-    v.y = 0;
-    ft_trig_pseudo_rotate( &v, angle );
+    FT_Vector_Unit( &v, angle );
 
     return FT_DivFix( v.y, v.x );
   }
@@ -340,6 +361,9 @@
   FT_Vector_Unit( FT_Vector*  vec,
                   FT_Angle    angle )
   {
+    if ( !vec )
+      return;
+
     vec->x = FT_TRIG_SCALE >> 8;
     vec->y = 0;
     ft_trig_pseudo_rotate( vec, angle );
@@ -366,30 +390,32 @@
     FT_Vector  v;
 
 
-    v.x   = vec->x;
-    v.y   = vec->y;
+    if ( !vec || !angle )
+      return;
 
-    if ( angle && ( v.x != 0 || v.y != 0 ) )
+    v = *vec;
+
+    if ( v.x == 0 && v.y == 0 )
+      return;
+
+    shift = ft_trig_prenorm( &v );
+    ft_trig_pseudo_rotate( &v, angle );
+    v.x = ft_trig_downscale( v.x );
+    v.y = ft_trig_downscale( v.y );
+
+    if ( shift > 0 )
     {
-      shift = ft_trig_prenorm( &v );
-      ft_trig_pseudo_rotate( &v, angle );
-      v.x = ft_trig_downscale( v.x );
-      v.y = ft_trig_downscale( v.y );
-
-      if ( shift > 0 )
-      {
-        FT_Int32  half = (FT_Int32)1L << ( shift - 1 );
+      FT_Int32  half = (FT_Int32)1L << ( shift - 1 );
 
 
-        vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
-        vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
-      }
-      else
-      {
-        shift  = -shift;
-        vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
-        vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
-      }
+      vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
+      vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
+    }
+    else
+    {
+      shift  = -shift;
+      vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
+      vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
     }
   }
 
@@ -403,6 +429,9 @@
     FT_Vector  v;
 
 
+    if ( !vec )
+      return 0;
+
     v = *vec;
 
     /* handle trivial cases */
@@ -422,7 +451,7 @@
     v.x = ft_trig_downscale( v.x );
 
     if ( shift > 0 )
-      return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
+      return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift;
 
     return (FT_Fixed)( (FT_UInt32)v.x << -shift );
   }
@@ -439,6 +468,9 @@
     FT_Vector  v;
 
 
+    if ( !vec || !length || !angle )
+      return;
+
     v = *vec;
 
     if ( v.x == 0 && v.y == 0 )
@@ -449,8 +481,8 @@
 
     v.x = ft_trig_downscale( v.x );
 
-    *length = ( shift >= 0 ) ?                      ( v.x >>  shift )
-                             : (FT_Fixed)( (FT_UInt32)v.x << -shift );
+    *length = shift >= 0 ?                      ( v.x >>  shift )
+                         : (FT_Fixed)( (FT_UInt32)v.x << -shift );
     *angle  = v.y;
   }
 
@@ -462,6 +494,9 @@
                         FT_Fixed    length,
                         FT_Angle    angle )
   {
+    if ( !vec )
+      return;
+
     vec->x = length;
     vec->y = 0;
 
@@ -478,11 +513,10 @@
     FT_Angle  delta = angle2 - angle1;
 
 
-    delta %= FT_ANGLE_2PI;
-    if ( delta < 0 )
+    while ( delta <= -FT_ANGLE_PI )
       delta += FT_ANGLE_2PI;
 
-    if ( delta > FT_ANGLE_PI )
+    while ( delta > FT_ANGLE_PI )
       delta -= FT_ANGLE_2PI;
 
     return delta;
diff --git a/src/base/fttype1.c b/src/base/fttype1.c
index 1d17402..5c0fce8 100644
--- a/src/base/fttype1.c
+++ b/src/base/fttype1.c
@@ -1,114 +1,127 @@
-/***************************************************************************/

-/*                                                                         */

-/*  fttype1.c                                                              */

-/*                                                                         */

-/*    FreeType utility file for PS names support (body).                   */

-/*                                                                         */

-/*  Copyright 2002-2004, 2011 by                                           */

-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */

-/*                                                                         */

-/*  This file is part of the FreeType project, and may only be used,       */

-/*  modified, and distributed under the terms of the FreeType project      */

-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */

-/*  this file you indicate that you have read the license and              */

-/*  understand and accept it fully.                                        */

-/*                                                                         */

-/***************************************************************************/

-

-

-#include <ft2build.h>

-#include FT_INTERNAL_OBJECTS_H

-#include FT_INTERNAL_SERVICE_H

-#include FT_SERVICE_POSTSCRIPT_INFO_H

-

-

-  /* documentation is in t1tables.h */

-

-  FT_EXPORT_DEF( FT_Error )

-  FT_Get_PS_Font_Info( FT_Face          face,

-                       PS_FontInfoRec*  afont_info )

-  {

-    FT_Error  error = FT_ERR( Invalid_Argument );

-

-

-    if ( face )

-    {

-      FT_Service_PsInfo  service = NULL;

-

-

-      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );

-

-      if ( service && service->ps_get_font_info )

-        error = service->ps_get_font_info( face, afont_info );

-    }

-

-    return error;

-  }

-

-

-  /* documentation is in t1tables.h */

-

-  FT_EXPORT_DEF( FT_Int )

-  FT_Has_PS_Glyph_Names( FT_Face  face )

-  {

-    FT_Int             result  = 0;

-    FT_Service_PsInfo  service = NULL;

-

-

-    if ( face )

-    {

-      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );

-

-      if ( service && service->ps_has_glyph_names )

-        result = service->ps_has_glyph_names( face );

-    }

-

-    return result;

-  }

-

-

-  /* documentation is in t1tables.h */

-

-  FT_EXPORT_DEF( FT_Error )

-  FT_Get_PS_Font_Private( FT_Face         face,

-                          PS_PrivateRec*  afont_private )

-  {

-    FT_Error  error = FT_ERR( Invalid_Argument );

-

-

-    if ( face )

-    {

-      FT_Service_PsInfo  service = NULL;

-

-

-      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );

-

-      if ( service && service->ps_get_font_private )

-        error = service->ps_get_font_private( face, afont_private );

-    }

-

-    return error;

-  }

-

-/* documentation is in t1tables.h */

-FT_EXPORT_DEF( FT_Long )

-FT_Get_PS_Font_Value( FT_Face       face,

-                      PS_Dict_Keys  key,

-                      FT_UInt       idx,

-                      void         *value,

-                      FT_Long       value_len )

-{

-  FT_Int             result  = 0;

-  FT_Service_PsInfo  service = NULL;

-

-  if ( face )

-  {

-    FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );

-      if ( service && service->ps_get_font_value )

-      result = service->ps_get_font_value( face, key, idx,

-                                           value, value_len );

-  }

-  return result;

-}

-

-/* END */

+/***************************************************************************/
+/*                                                                         */
+/*  fttype1.c                                                              */
+/*                                                                         */
+/*    FreeType utility file for PS names support (body).                   */
+/*                                                                         */
+/*  Copyright 2002-2016 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+
+  /* documentation is in t1tables.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_PS_Font_Info( FT_Face          face,
+                       PS_FontInfoRec*  afont_info )
+  {
+    FT_Error           error;
+    FT_Service_PsInfo  service;
+
+
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
+
+    if ( !afont_info )
+      return FT_THROW( Invalid_Argument );
+
+    FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+    if ( service && service->ps_get_font_info )
+      error = service->ps_get_font_info( face, afont_info );
+    else
+      error = FT_THROW( Invalid_Argument );
+
+    return error;
+  }
+
+
+  /* documentation is in t1tables.h */
+
+  FT_EXPORT_DEF( FT_Int )
+  FT_Has_PS_Glyph_Names( FT_Face  face )
+  {
+    FT_Int             result = 0;
+    FT_Service_PsInfo  service;
+
+
+    if ( face )
+    {
+      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+      if ( service && service->ps_has_glyph_names )
+        result = service->ps_has_glyph_names( face );
+    }
+
+    return result;
+  }
+
+
+  /* documentation is in t1tables.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_PS_Font_Private( FT_Face         face,
+                          PS_PrivateRec*  afont_private )
+  {
+    FT_Error           error;
+    FT_Service_PsInfo  service;
+
+
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
+
+    if ( !afont_private )
+      return FT_THROW( Invalid_Argument );
+
+    FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+    if ( service && service->ps_get_font_private )
+      error = service->ps_get_font_private( face, afont_private );
+    else
+      error = FT_THROW( Invalid_Argument );
+
+    return error;
+  }
+
+
+  /* documentation is in t1tables.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_Get_PS_Font_Value( FT_Face       face,
+                        PS_Dict_Keys  key,
+                        FT_UInt       idx,
+                        void         *value,
+                        FT_Long       value_len )
+  {
+    FT_Int             result  = 0;
+    FT_Service_PsInfo  service = NULL;
+
+
+    if ( face )
+    {
+      FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+      if ( service && service->ps_get_font_value )
+        result = service->ps_get_font_value( face, key, idx,
+                                             value, value_len );
+    }
+
+    return result;
+  }
+
+
+/* END */
diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index 9f37189..fad7d1a 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility file for memory and list management (body).         */
 /*                                                                         */
-/*  Copyright 2002, 2004-2007, 2013 by                                     */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -180,7 +180,7 @@
               FT_Error    *p_error )
   {
     FT_Error    error;
-    FT_Pointer  p = ft_mem_qalloc( memory, size, &error );
+    FT_Pointer  p = ft_mem_qalloc( memory, (FT_Long)size, &error );
 
 
     if ( !error && address )
@@ -245,6 +245,9 @@
     FT_ListNode  cur;
 
 
+    if ( !list )
+      return NULL;
+
     cur = list->head;
     while ( cur )
     {
@@ -254,7 +257,7 @@
       cur = cur->next;
     }
 
-    return (FT_ListNode)0;
+    return NULL;
   }
 
 
@@ -264,10 +267,15 @@
   FT_List_Add( FT_List      list,
                FT_ListNode  node )
   {
-    FT_ListNode  before = list->tail;
+    FT_ListNode  before;
 
 
-    node->next = 0;
+    if ( !list || !node )
+      return;
+
+    before = list->tail;
+
+    node->next = NULL;
     node->prev = before;
 
     if ( before )
@@ -285,11 +293,16 @@
   FT_List_Insert( FT_List      list,
                   FT_ListNode  node )
   {
-    FT_ListNode  after = list->head;
+    FT_ListNode  after;
 
 
+    if ( !list || !node )
+      return;
+
+    after = list->head;
+
     node->next = after;
-    node->prev = 0;
+    node->prev = NULL;
 
     if ( !after )
       list->tail = node;
@@ -309,6 +322,9 @@
     FT_ListNode  before, after;
 
 
+    if ( !list || !node )
+      return;
+
     before = node->prev;
     after  = node->next;
 
@@ -333,6 +349,9 @@
     FT_ListNode  before, after;
 
 
+    if ( !list || !node )
+      return;
+
     before = node->prev;
     after  = node->next;
 
@@ -347,7 +366,7 @@
     else
       list->tail = before;
 
-    node->prev       = 0;
+    node->prev       = NULL;
     node->next       = list->head;
     list->head->prev = node;
     list->head       = node;
@@ -357,14 +376,19 @@
   /* documentation is in ftlist.h */
 
   FT_EXPORT_DEF( FT_Error )
-  FT_List_Iterate( FT_List            list,
-                   FT_List_Iterator   iterator,
-                   void*              user )
+  FT_List_Iterate( FT_List           list,
+                   FT_List_Iterator  iterator,
+                   void*             user )
   {
-    FT_ListNode  cur   = list->head;
+    FT_ListNode  cur;
     FT_Error     error = FT_Err_Ok;
 
 
+    if ( !list || !iterator )
+      return FT_THROW( Invalid_Argument );
+
+    cur = list->head;
+
     while ( cur )
     {
       FT_ListNode  next = cur->next;
@@ -392,6 +416,9 @@
     FT_ListNode  cur;
 
 
+    if ( !list || !memory )
+      return;
+
     cur = list->head;
     while ( cur )
     {
@@ -406,8 +433,8 @@
       cur = next;
     }
 
-    list->head = 0;
-    list->tail = 0;
+    list->head = NULL;
+    list->tail = NULL;
   }
 
 
diff --git a/src/base/ftwinfnt.c b/src/base/ftwinfnt.c
index 463ae76..89e9155 100644
--- a/src/base/ftwinfnt.c
+++ b/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for accessing Windows FNT specific info (body).         */
 /*                                                                         */
-/*  Copyright 2003, 2004 by                                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include FT_WINFONTS_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_SERVICE_WINFNT_H
@@ -32,17 +33,18 @@
     FT_Error           error;
 
 
-    error = FT_ERR( Invalid_Argument );
+    if ( !face )
+      return FT_THROW( Invalid_Face_Handle );
 
-    if ( face != NULL )
-    {
-      FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
+    if ( !header )
+      return FT_THROW( Invalid_Argument );
 
-      if ( service != NULL )
-      {
-        error = service->get_header( face, header );
-      }
-    }
+    FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
+
+    if ( service )
+      error = service->get_header( face, header );
+    else
+      error = FT_THROW( Invalid_Argument );
 
     return error;
   }
diff --git a/src/base/md5.c b/src/base/md5.c
index 52d96ac..b235e17 100644
--- a/src/base/md5.c
+++ b/src/base/md5.c
@@ -63,12 +63,19 @@
 	(a) += (b);
 
 /*
- * SET reads 4 input bytes in little-endian byte order and stores them
- * in a properly aligned word in host byte order.
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
  *
- * The check for little-endian architectures that tolerate unaligned
- * memory accesses is just an optimization.  Nothing will break if it
- * doesn't work.
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization.  Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD5_u32plus.  In practice, this problem may occur if these MD5 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations.  For the time being, keeping these MD5 routines in
+ * their own translation unit avoids the problem.
  */
 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
 #define SET(n) \
@@ -87,8 +94,8 @@
 #endif
 
 /*
- * This processes one or more 64-byte data blocks, but does NOT update
- * the bit counters.  There are no alignment requirements.
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters.  There are no alignment requirements.
  */
 static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 {
@@ -242,6 +249,12 @@
 	memcpy(ctx->buffer, data, size);
 }
 
+#define OUT(dst, src) \
+	(dst)[0] = (unsigned char)(src); \
+	(dst)[1] = (unsigned char)((src) >> 8); \
+	(dst)[2] = (unsigned char)((src) >> 16); \
+	(dst)[3] = (unsigned char)((src) >> 24);
+
 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
 {
 	unsigned long used, available;
@@ -262,33 +275,15 @@
 	memset(&ctx->buffer[used], 0, available - 8);
 
 	ctx->lo <<= 3;
-	ctx->buffer[56] = ctx->lo;
-	ctx->buffer[57] = ctx->lo >> 8;
-	ctx->buffer[58] = ctx->lo >> 16;
-	ctx->buffer[59] = ctx->lo >> 24;
-	ctx->buffer[60] = ctx->hi;
-	ctx->buffer[61] = ctx->hi >> 8;
-	ctx->buffer[62] = ctx->hi >> 16;
-	ctx->buffer[63] = ctx->hi >> 24;
+	OUT(&ctx->buffer[56], ctx->lo)
+	OUT(&ctx->buffer[60], ctx->hi)
 
 	body(ctx, ctx->buffer, 64);
 
-	result[0] = ctx->a;
-	result[1] = ctx->a >> 8;
-	result[2] = ctx->a >> 16;
-	result[3] = ctx->a >> 24;
-	result[4] = ctx->b;
-	result[5] = ctx->b >> 8;
-	result[6] = ctx->b >> 16;
-	result[7] = ctx->b >> 24;
-	result[8] = ctx->c;
-	result[9] = ctx->c >> 8;
-	result[10] = ctx->c >> 16;
-	result[11] = ctx->c >> 24;
-	result[12] = ctx->d;
-	result[13] = ctx->d >> 8;
-	result[14] = ctx->d >> 16;
-	result[15] = ctx->d >> 24;
+	OUT(&result[0], ctx->a)
+	OUT(&result[4], ctx->b)
+	OUT(&result[8], ctx->c)
+	OUT(&result[12], ctx->d)
 
 	memset(ctx, 0, sizeof(*ctx));
 }
diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c
index 01be88c..ac3290c 100644
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType basic cache interface (body).                           */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009-2011, 2013, 2014 by                          */
+/*  Copyright 2003-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -45,8 +45,8 @@
           FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
                    (a)->load_flags == (b)->load_flags               )
 
-#define FTC_BASIC_ATTR_HASH( a )                                   \
-          ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
+#define FTC_BASIC_ATTR_HASH( a )                                     \
+          ( FTC_SCALER_HASH( &(a)->scaler ) + 31 * (a)->load_flags )
 
 
   typedef struct  FTC_BasicQueryRec_
@@ -110,10 +110,9 @@
       return result;
 
     if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
-    {
-      FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
-      FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
-    }
+      FT_TRACE1(( "ftc_basic_family_get_count:"
+                  " too large number of glyphs in this face, truncated\n",
+                  face->num_glyphs ));
 
     if ( !error )
       result = (FT_UInt)face->num_glyphs;
@@ -139,8 +138,10 @@
       FT_Face  face = size->face;
 
 
-      error = FT_Load_Glyph( face, gindex,
-                             family->attrs.load_flags | FT_LOAD_RENDER );
+      error = FT_Load_Glyph(
+                face,
+                gindex,
+                (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
       if ( !error )
         *aface = face;
     }
@@ -170,7 +171,9 @@
     {
       face = size->face;
 
-      error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
+      error = FT_Load_Glyph( face,
+                             gindex,
+                             (FT_Int)family->attrs.load_flags );
       if ( !error )
       {
         if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
@@ -284,10 +287,10 @@
     FTC_BasicQueryRec  query;
     FTC_Node           node = 0; /* make compiler happy */
     FT_Error           error;
-    FT_PtrDist         hash;
+    FT_Offset          hash;
 
 
-    /* some argument checks are delayed to FTC_Cache_Lookup */
+    /* some argument checks are delayed to `FTC_Cache_Lookup' */
     if ( !aglyph )
     {
       error = FT_THROW( Invalid_Argument );
@@ -298,18 +301,15 @@
     if ( anode )
       *anode  = NULL;
 
-    {
-      if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
-      {
-        FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
-        FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
-      }
+    if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+      FT_TRACE1(( "FTC_ImageCache_Lookup:"
+                  " higher bits in load_flags 0x%x are dropped\n",
+                  (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
 
-      query.attrs.scaler.face_id = type->face_id;
-      query.attrs.scaler.width   = type->width;
-      query.attrs.scaler.height  = type->height;
-      query.attrs.load_flags     = (FT_UInt)type->flags;
-    }
+    query.attrs.scaler.face_id = type->face_id;
+    query.attrs.scaler.width   = type->width;
+    query.attrs.scaler.height  = type->height;
+    query.attrs.load_flags     = (FT_UInt)type->flags;
 
     query.attrs.scaler.pixel = 1;
     query.attrs.scaler.x_res = 0;  /* make compilers happy */
@@ -360,10 +360,10 @@
     FTC_BasicQueryRec  query;
     FTC_Node           node = 0; /* make compiler happy */
     FT_Error           error;
-    FT_PtrDist         hash;
+    FT_Offset          hash;
 
 
-    /* some argument checks are delayed to FTC_Cache_Lookup */
+    /* some argument checks are delayed to `FTC_Cache_Lookup' */
     if ( !aglyph || !scaler )
     {
       error = FT_THROW( Invalid_Argument );
@@ -374,12 +374,11 @@
     if ( anode )
       *anode  = NULL;
 
-    /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+    /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
     if ( load_flags > FT_UINT_MAX )
-    {
-      FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
-      FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
-    }
+      FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
+                  " higher bits in load_flags 0x%x are dropped\n",
+                  load_flags & ~((FT_ULong)FT_UINT_MAX) ));
 
     query.attrs.scaler     = scaler[0];
     query.attrs.load_flags = (FT_UInt)load_flags;
@@ -471,30 +470,27 @@
     FT_Error           error;
     FTC_BasicQueryRec  query;
     FTC_Node           node = 0; /* make compiler happy */
-    FT_PtrDist         hash;
+    FT_Offset          hash;
 
 
     if ( anode )
       *anode = NULL;
 
-    /* other argument checks delayed to FTC_Cache_Lookup */
+    /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !ansbit )
       return FT_THROW( Invalid_Argument );
 
     *ansbit = NULL;
 
-    {
-      if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
-      {
-        FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
-        FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
-      }
+    if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+      FT_TRACE1(( "FTC_ImageCache_Lookup:"
+                  " higher bits in load_flags 0x%x are dropped\n",
+                  (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
 
-      query.attrs.scaler.face_id = type->face_id;
-      query.attrs.scaler.width   = type->width;
-      query.attrs.scaler.height  = type->height;
-      query.attrs.load_flags     = (FT_UInt)type->flags;
-    }
+    query.attrs.scaler.face_id = type->face_id;
+    query.attrs.scaler.width   = type->width;
+    query.attrs.scaler.height  = type->height;
+    query.attrs.load_flags     = (FT_UInt)type->flags;
 
     query.attrs.scaler.pixel = 1;
     query.attrs.scaler.x_res = 0;  /* make compilers happy */
@@ -549,24 +545,23 @@
     FT_Error           error;
     FTC_BasicQueryRec  query;
     FTC_Node           node = 0; /* make compiler happy */
-    FT_PtrDist         hash;
+    FT_Offset          hash;
 
 
     if ( anode )
         *anode = NULL;
 
-    /* other argument checks delayed to FTC_Cache_Lookup */
+    /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !ansbit || !scaler )
         return FT_THROW( Invalid_Argument );
 
     *ansbit = NULL;
 
-    /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+    /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
     if ( load_flags > FT_UINT_MAX )
-    {
-      FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
-      FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
-    }
+      FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
+                  " higher bits in load_flags 0x%x are dropped\n",
+                  load_flags & ~((FT_ULong)FT_UINT_MAX) ));
 
     query.attrs.scaler     = scaler[0];
     query.attrs.load_flags = (FT_UInt)load_flags;
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index f20dd45..d8c5b99 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType internal cache interface (body).                        */
 /*                                                                         */
-/*  Copyright 2000-2007, 2009-2011, 2013 by                                */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -88,16 +88,16 @@
    * body for FTC_NODE__TOP_FOR_HASH( cache, hash )
    */
   FT_LOCAL_DEF( FTC_Node* )
-  ftc_get_top_node_for_hash( FTC_Cache   cache,
-                             FT_PtrDist  hash )
+  ftc_get_top_node_for_hash( FTC_Cache  cache,
+                             FT_Offset  hash )
   {
     FTC_Node*  pnode;
-    FT_UInt    idx;
+    FT_Offset  idx;
 
 
-    idx = (FT_UInt)( hash & cache->mask );
+    idx = hash & cache->mask;
     if ( idx < cache->p )
-      idx = (FT_UInt)( hash & ( 2 * cache->mask + 1 ) );
+      idx = hash & ( 2 * cache->mask + 1 );
     pnode = cache->buckets + idx;
     return pnode;
   }
@@ -414,7 +414,7 @@
 
   static void
   ftc_cache_add( FTC_Cache  cache,
-                 FT_PtrDist hash,
+                 FT_Offset  hash,
                  FTC_Node   node )
   {
     node->hash        = hash;
@@ -442,7 +442,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   FTC_Cache_NewNode( FTC_Cache   cache,
-                     FT_PtrDist  hash,
+                     FT_Offset   hash,
                      FT_Pointer  query,
                      FTC_Node   *anode )
   {
@@ -481,7 +481,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   FTC_Cache_Lookup( FTC_Cache   cache,
-                    FT_PtrDist  hash,
+                    FT_Offset   hash,
                     FT_Pointer  query,
                     FTC_Node   *anode )
   {
diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h
index 4155f32..4e17c7a 100644
--- a/src/cache/ftccache.h
+++ b/src/cache/ftccache.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType internal cache interface (specification).                   */
 /*                                                                         */
-/*  Copyright 2000-2007, 2009-2011, 2013 by                                */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,8 +24,8 @@
 
 FT_BEGIN_HEADER
 
-#define _FTC_FACE_ID_HASH( i )                                                \
-          ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
+#define _FTC_FACE_ID_HASH( i )                                  \
+          ( ( (FT_Offset)(i) >> 3 ) ^ ( (FT_Offset)(i) << 7 ) )
 
   /* handle to cache object */
   typedef struct FTC_CacheRec_*  FTC_Cache;
@@ -59,7 +59,7 @@
   {
     FTC_MruNodeRec  mru;          /* circular mru list pointer           */
     FTC_Node        link;         /* used for hashing                    */
-    FT_PtrDist      hash;         /* used for hashing too                */
+    FT_Offset       hash;         /* used for hashing too                */
     FT_UShort       cache_index;  /* index of cache the node belongs to  */
     FT_Short        ref_count;    /* reference count for this node       */
 
@@ -80,8 +80,8 @@
               : ( ( hash ) &   ( cache )->mask ) ) )
 #else
   FT_LOCAL( FTC_Node* )
-  ftc_get_top_node_for_hash( FTC_Cache   cache,
-                             FT_PtrDist  hash );
+  ftc_get_top_node_for_hash( FTC_Cache  cache,
+                             FT_Offset  hash );
 #define FTC_NODE__TOP_FOR_HASH( cache, hash )            \
         ftc_get_top_node_for_hash( ( cache ), ( hash ) )
 #endif
@@ -179,14 +179,14 @@
 #ifndef FTC_INLINE
   FT_LOCAL( FT_Error )
   FTC_Cache_Lookup( FTC_Cache   cache,
-                    FT_PtrDist  hash,
+                    FT_Offset   hash,
                     FT_Pointer  query,
                     FTC_Node   *anode );
 #endif
 
   FT_LOCAL( FT_Error )
   FTC_Cache_NewNode( FTC_Cache   cache,
-                     FT_PtrDist  hash,
+                     FT_Offset   hash,
                      FT_Pointer  query,
                      FTC_Node   *anode );
 
@@ -211,7 +211,7 @@
   FT_BEGIN_STMNT                                                         \
     FTC_Node             *_bucket, *_pnode, _node;                       \
     FTC_Cache             _cache   = FTC_CACHE(cache);                   \
-    FT_PtrDist            _hash    = (FT_PtrDist)(hash);                 \
+    FT_Offset             _hash    = (FT_Offset)(hash);                  \
     FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);    \
     FT_Bool               _list_changed = FALSE;                         \
                                                                          \
diff --git a/src/cache/ftccback.h b/src/cache/ftccback.h
index 9528279..b3237d5 100644
--- a/src/cache/ftccback.h
+++ b/src/cache/ftccback.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Callback functions of the caching sub-system (specification only).   */
 /*                                                                         */
-/*  Copyright 2004-2006, 2011, 2013 by                                     */
+/*  Copyright 2004-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c
index b2e9609..b826222 100644
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType CharMap cache (body)                                        */
 /*                                                                         */
-/*  Copyright 2000-2014 by                                                 */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -63,8 +63,6 @@
   } FTC_CMapQueryRec, *FTC_CMapQuery;
 
 #define FTC_CMAP_QUERY( x )  ((FTC_CMapQuery)(x))
-#define FTC_CMAP_QUERY_HASH( x )                                         \
-          FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
 
   /* the cmap cache node */
   typedef struct  FTC_CMapNodeRec_
@@ -78,8 +76,6 @@
   } FTC_CMapNodeRec, *FTC_CMapNode;
 
 #define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
-#define FTC_CMAP_NODE_HASH( x )                                      \
-          FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
 
   /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
   /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet   */
@@ -242,7 +238,7 @@
     FTC_Node          node;
     FT_Error          error;
     FT_UInt           gindex = 0;
-    FT_PtrDist        hash;
+    FT_Offset         hash;
     FT_Int            no_cmap_change = 0;
 
 
@@ -263,11 +259,14 @@
       return 0;
     }
 
+    if ( !face_id )
+      return 0;
+
     query.face_id    = face_id;
     query.cmap_index = (FT_UInt)cmap_index;
     query.char_code  = char_code;
 
-    hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
+    hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );
 
 #if 1
     FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
@@ -301,12 +300,6 @@
       if ( error )
         goto Exit;
 
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-      /* something rotten can happen with rogue clients */
-      if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
-        return 0; /* XXX: should return appropriate error */
-#endif
-
       if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
       {
         FT_CharMap  old, cmap  = NULL;
diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c
index 441e177..343b8a7 100644
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Glyph Image (FT_Glyph) cache (body).                        */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2004, 2006, 2009, 2011 by                   */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -185,7 +185,7 @@
 
   FT_LOCAL_DEF( FT_Error )
   FTC_GCache_Lookup( FTC_GCache   cache,
-                     FT_PtrDist   hash,
+                     FT_Offset    hash,
                      FT_UInt      gindex,
                      FTC_GQuery   query,
                      FTC_Node    *anode )
diff --git a/src/cache/ftcglyph.h b/src/cache/ftcglyph.h
index 5fed19c..6cadbe2 100644
--- a/src/cache/ftcglyph.h
+++ b/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType abstract glyph cache (specification).                       */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 by                   */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -260,7 +260,7 @@
 #ifndef FTC_INLINE
   FT_LOCAL( FT_Error )
   FTC_GCache_Lookup( FTC_GCache   cache,
-                     FT_PtrDist   hash,
+                     FT_Offset    hash,
                      FT_UInt      gindex,
                      FTC_GQuery   query,
                      FTC_Node    *anode );
diff --git a/src/cache/ftcmanag.h b/src/cache/ftcmanag.h
index 0aec33c..c6787b7 100644
--- a/src/cache/ftcmanag.h
+++ b/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Cache Manager (specification).                              */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2004, 2006, 2010, 2013 by                   */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c
index dc8b4cc..10ce4f3 100644
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType MRU support (body).                                         */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2006, 2009 by                                    */
+/*  Copyright 2003-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c
index 6df1c19..8141719 100644
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType sbits manager (body).                                       */
 /*                                                                         */
-/*  Copyright 2000-2006, 2009-2011, 2013 by                                */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -52,7 +52,7 @@
     if ( pitch < 0 )
       pitch = -pitch;
 
-    size = (FT_ULong)( pitch * bitmap->rows );
+    size = (FT_ULong)pitch * bitmap->rows;
 
     if ( !FT_ALLOC( sbit->buffer, size ) )
       FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
@@ -142,12 +142,12 @@
         goto BadGlyph;
       }
 
-      /* Check that our values fit into 8-bit containers!       */
+      /* Check whether our values fit into 8-bit containers!    */
       /* If this is not the case, our bitmap is too large       */
       /* and we will leave it as `missing' with sbit.buffer = 0 */
 
-#define CHECK_CHAR( d )  ( temp = (FT_Char)d, temp == d )
-#define CHECK_BYTE( d )  ( temp = (FT_Byte)d, temp == d )
+#define CHECK_CHAR( d )  ( temp = (FT_Char)d, (FT_Int) temp == (FT_Int) d )
+#define CHECK_BYTE( d )  ( temp = (FT_Byte)d, (FT_UInt)temp == (FT_UInt)d )
 
       /* horizontal advance in pixels */
       xadvance = ( slot->advance.x + 32 ) >> 6;
@@ -181,7 +181,7 @@
 
       /* now, compute size */
       if ( asize )
-        *asize = FT_ABS( sbit->pitch ) * sbit->height;
+        *asize = (FT_ULong)FT_ABS( sbit->pitch ) * sbit->height;
 
     } /* glyph loading successful */
 
@@ -302,7 +302,7 @@
           pitch = -pitch;
 
         /* add the size of a given glyph image */
-        size += pitch * sbit->height;
+        size += (FT_Offset)pitch * sbit->height;
       }
     }
 
diff --git a/src/cache/ftcsbits.h b/src/cache/ftcsbits.h
index df55dca..5a2fa1a 100644
--- a/src/cache/ftcsbits.h
+++ b/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    A small-bitmap cache (specification).                                */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2006, 2011 by                         */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cff/cf2arrst.c b/src/cff/cf2arrst.c
index c8d6f13..89f3e9f 100644
--- a/src/cff/cf2arrst.c
+++ b/src/cff/cf2arrst.c
@@ -101,10 +101,10 @@
       FT_Error   error  = FT_Err_Ok;        /* for FT_REALLOC */
       FT_Memory  memory = arrstack->memory; /* for FT_REALLOC */
 
-      FT_Long  newSize = (FT_Long)( numElements * arrstack->sizeItem );
+      size_t  newSize = numElements * arrstack->sizeItem;
 
 
-      if ( numElements > LONG_MAX / arrstack->sizeItem )
+      if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
         goto exit;
 
 
diff --git a/src/cff/cf2arrst.h b/src/cff/cf2arrst.h
index ff5ad8b..3c21a3b 100644
--- a/src/cff/cf2arrst.h
+++ b/src/cff/cf2arrst.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2ARRST_H__
-#define __CF2ARRST_H__
+#ifndef CF2ARRST_H_
+#define CF2ARRST_H_
 
 
 #include "cf2error.h"
@@ -94,7 +94,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2ARRST_H__ */
+#endif /* CF2ARRST_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2blues.h b/src/cff/cf2blues.h
index 2f38fca..96fb60f 100644
--- a/src/cff/cf2blues.h
+++ b/src/cff/cf2blues.h
@@ -65,8 +65,8 @@
    */
 
 
-#ifndef __CF2BLUES_H__
-#define __CF2BLUES_H__
+#ifndef CF2BLUES_H_
+#define CF2BLUES_H_
 
 
 #include "cf2glue.h"
@@ -179,7 +179,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2BLUES_H__ */
+#endif /* CF2BLUES_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2error.h b/src/cff/cf2error.h
index 6453ebc..512edd1 100644
--- a/src/cff/cf2error.h
+++ b/src/cff/cf2error.h
@@ -36,13 +36,13 @@
 /***************************************************************************/
 
 
-#ifndef __CF2ERROR_H__
-#define __CF2ERROR_H__
+#ifndef CF2ERROR_H_
+#define CF2ERROR_H_
 
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  CF2_Err_
@@ -70,7 +70,7 @@
    * Upon a function call if the error code is anything other than
    * `FT_Err_Ok', which is guaranteed to be zero, we
    * will return without altering that error.  This will allow the
-   * error to propogate and be handled at the appropriate location in
+   * error to propagate and be handled at the appropriate location in
    * the code.
    *
    * This allows a style of code where the error code is initialized
@@ -113,7 +113,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2ERROR_H__ */
+#endif /* CF2ERROR_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2fixed.h b/src/cff/cf2fixed.h
index ed1452a..74af377 100644
--- a/src/cff/cf2fixed.h
+++ b/src/cff/cf2fixed.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2FIXED_H__
-#define __CF2FIXED_H__
+#ifndef CF2FIXED_H_
+#define CF2FIXED_H_
 
 
 FT_BEGIN_HEADER
@@ -57,22 +57,22 @@
   /* in C 89, left and right shift of negative numbers is  */
   /* implementation specific behaviour in the general case */
 
-#define cf2_intToFixed( i )                                    \
+#define cf2_intToFixed( i )                                              \
           ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
-#define cf2_fixedToInt( x )                                    \
+#define cf2_fixedToInt( x )                                              \
           ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
-#define cf2_fixedRound( x )                                    \
-          ( (CF2_Fixed)( ( (x) + 0x8000 ) & 0xFFFF0000L ) )
-#define cf2_floatToFixed( f )                                  \
+#define cf2_fixedRound( x )                                              \
+          ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) )
+#define cf2_floatToFixed( f )                                            \
           ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
-#define cf2_fixedAbs( x )                                      \
+#define cf2_fixedAbs( x )                                                \
           ( (x) < 0 ? -(x) : (x) )
-#define cf2_fixedFloor( x )                                    \
-          ( (CF2_Fixed)( (x) & 0xFFFF0000L ) )
-#define cf2_fixedFraction( x )                                 \
+#define cf2_fixedFloor( x )                                              \
+          ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) )
+#define cf2_fixedFraction( x )                                           \
           ( (x) - cf2_fixedFloor( x ) )
-#define cf2_fracToFixed( x )                                   \
-          ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 )             \
+#define cf2_fracToFixed( x )                                             \
+          ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 )                       \
                     :  ( (  (x) + 0x2000 ) >> 14 ) )
 
 
@@ -89,7 +89,7 @@
 FT_END_HEADER
 
 
-#endif /*  __CF2FIXED_H__ */
+#endif /* CF2FIXED_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
index 6e99dc2..83fd348 100644
--- a/src/cff/cf2font.c
+++ b/src/cff/cf2font.c
@@ -36,6 +36,9 @@
 /***************************************************************************/
 
 
+#include <ft2build.h>
+#include FT_INTERNAL_CALC_H
+
 #include "cf2ft.h"
 
 #include "cf2glue.h"
@@ -105,6 +108,7 @@
     /* adjusting for emRatio converts darkenAmount to character */
     /* space (font units).                                      */
     CF2_Fixed  stemWidthPer1000, scaledStem;
+    FT_Int     logBase2;
 
 
     *darkenAmount = 0;
@@ -131,25 +135,32 @@
       /* convert from true character space to 1000 unit character space; */
       /* add synthetic emboldening effect                                */
 
-      /* we have to assure that the computation of `scaledStem' */
-      /* and `stemWidthPer1000' don't overflow                  */
+      /* `stemWidthPer1000' will not overflow for a legitimate font      */
 
       stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
 
-      if ( emRatio > CF2_FIXED_ONE                          &&
-           stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
-      {
-        stemWidthPer1000 = 0;                      /* to pacify compiler */
-        scaledStem       = cf2_intToFixed( x4 );
-      }
-      else
-      {
-        scaledStem = FT_MulFix( stemWidthPer1000, ppem );
+      /* `scaledStem' can easily overflow, so we must clamp its maximum  */
+      /* value; the test doesn't need to be precise, but must be         */
+      /* conservative.  The clamp value (default 2333) where             */
+      /* `darkenAmount' is zero is well below the overflow value of      */
+      /* 32767.                                                          */
+      /*                                                                 */
+      /* FT_MSB computes the integer part of the base 2 logarithm.  The  */
+      /* number of bits for the product is 1 or 2 more than the sum of   */
+      /* logarithms; remembering that the 16 lowest bits of the fraction */
+      /* are dropped this is correct to within a factor of almost 4.     */
+      /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and   */
+      /* is flagged as possible overflow because 0xFF.FFFF * 0xFF.FFFF = */
+      /* 0xFFFF.FE00 is also 23+23.                                      */
 
-        if ( ppem > CF2_FIXED_ONE           &&
-             scaledStem <= stemWidthPer1000 )
-          scaledStem = cf2_intToFixed( x4 );
-      }
+      logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
+                   FT_MSB( (FT_UInt32)ppem );
+
+      if ( logBase2 >= 46 )
+        /* possible overflow */
+        scaledStem = cf2_intToFixed( x4 );
+      else
+        scaledStem = FT_MulFix( stemWidthPer1000, ppem );
 
       /* now apply the darkening parameters */
 
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
index d8860ce..bd05e69 100644
--- a/src/cff/cf2font.h
+++ b/src/cff/cf2font.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2FONT_H__
-#define __CF2FONT_H__
+#ifndef CF2FONT_H_
+#define CF2FONT_H_
 
 
 #include "cf2ft.h"
@@ -48,7 +48,13 @@
 
 
 #define CF2_OPERAND_STACK_SIZE  48
-#define CF2_MAX_SUBR            10 /* maximum subroutine nesting */
+#define CF2_MAX_SUBR            16 /* maximum subroutine nesting;         */
+                                   /* only 10 are allowed but there exist */
+                                   /* fonts like `HiraKakuProN-W3.ttf'    */
+                                   /* (Hiragino Kaku Gothic ProN W3;      */
+                                   /* 8.2d6e1; 2014-12-19) that exceed    */
+                                   /* this limit                          */
+#define CF2_STORAGE_SIZE        32
 
 
   /* typedef is in `cf2glue.h' */
@@ -110,7 +116,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2FONT_H__ */
+#endif /* CF2FONT_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index cb8d31c..55f3206 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -142,6 +142,8 @@
   cf2_builder_lineTo( CF2_OutlineCallbacks      callbacks,
                       const CF2_CallbackParams  params )
   {
+    FT_Error  error;
+
     /* downcast the object pointer */
     CF2_Outline   outline = (CF2_Outline)callbacks;
     CFF_Builder*  builder;
@@ -156,15 +158,27 @@
     {
       /* record the move before the line; also check points and set */
       /* `path_begun'                                               */
-      cff_builder_start_point( builder,
-                               params->pt0.x,
-                               params->pt0.y );
+      error = cff_builder_start_point( builder,
+                                       params->pt0.x,
+                                       params->pt0.y );
+      if ( error )
+      {
+        if ( !*callbacks->error )
+          *callbacks->error =  error;
+        return;
+      }
     }
 
     /* `cff_builder_add_point1' includes a check_points call for one point */
-    cff_builder_add_point1( builder,
-                            params->pt1.x,
-                            params->pt1.y );
+    error = cff_builder_add_point1( builder,
+                                    params->pt1.x,
+                                    params->pt1.y );
+    if ( error )
+    {
+      if ( !*callbacks->error )
+        *callbacks->error =  error;
+      return;
+    }
   }
 
 
@@ -172,6 +186,8 @@
   cf2_builder_cubeTo( CF2_OutlineCallbacks      callbacks,
                       const CF2_CallbackParams  params )
   {
+    FT_Error  error;
+
     /* downcast the object pointer */
     CF2_Outline   outline = (CF2_Outline)callbacks;
     CFF_Builder*  builder;
@@ -186,13 +202,25 @@
     {
       /* record the move before the line; also check points and set */
       /* `path_begun'                                               */
-      cff_builder_start_point( builder,
-                               params->pt0.x,
-                               params->pt0.y );
+      error = cff_builder_start_point( builder,
+                                       params->pt0.x,
+                                       params->pt0.y );
+      if ( error )
+      {
+        if ( !*callbacks->error )
+          *callbacks->error =  error;
+        return;
+      }
     }
 
     /* prepare room for 3 points: 2 off-curve, 1 on-curve */
-    cff_check_points( builder, 3 );
+    error = cff_check_points( builder, 3 );
+    if ( error )
+    {
+      if ( !*callbacks->error )
+        *callbacks->error =  error;
+      return;
+    }
 
     cff_builder_add_point( builder,
                            params->pt1.x,
@@ -516,14 +544,17 @@
   /* return 0 on success                                   */
   FT_LOCAL_DEF( CF2_Int )
   cf2_initGlobalRegionBuffer( CFF_Decoder*  decoder,
-                              CF2_UInt      idx,
+                              CF2_Int       subrNum,
                               CF2_Buffer    buf )
   {
+    CF2_UInt  idx;
+
+
     FT_ASSERT( decoder );
 
     FT_ZERO( buf );
 
-    idx += decoder->globals_bias;
+    idx = (CF2_UInt)( subrNum + decoder->globals_bias );
     if ( idx >= decoder->num_globals )
       return TRUE;     /* error */
 
@@ -541,7 +572,7 @@
   /* used for seac component                           */
   FT_LOCAL_DEF( FT_Error )
   cf2_getSeacComponent( CFF_Decoder*  decoder,
-                        CF2_UInt      code,
+                        CF2_Int       code,
                         CF2_Buffer    buf )
   {
     CF2_Int   gid;
@@ -554,12 +585,21 @@
 
     FT_ZERO( buf );
 
-    gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
-    if ( gid < 0 )
-      return FT_THROW( Invalid_Glyph_Format );
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+    /* Incremental fonts don't necessarily have valid charsets.        */
+    /* They use the character code, not the glyph index, in this case. */
+    if ( decoder->builder.face->root.internal->incremental_interface )
+      gid = code;
+    else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+    {
+      gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
+      if ( gid < 0 )
+        return FT_THROW( Invalid_Glyph_Format );
+    }
 
     error = cff_get_glyph_data( decoder->builder.face,
-                                gid,
+                                (CF2_UInt)gid,
                                 &charstring,
                                 &len );
     /* TODO: for now, just pass the FreeType error through */
@@ -591,14 +631,17 @@
 
   FT_LOCAL_DEF( CF2_Int )
   cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
-                             CF2_UInt      idx,
+                             CF2_Int       subrNum,
                              CF2_Buffer    buf )
   {
+    CF2_UInt  idx;
+
+
     FT_ASSERT( decoder );
 
     FT_ZERO( buf );
 
-    idx += decoder->locals_bias;
+    idx = (CF2_UInt)( subrNum + decoder->locals_bias );
     if ( idx >= decoder->num_locals )
       return TRUE;     /* error */
 
diff --git a/src/cff/cf2ft.h b/src/cff/cf2ft.h
index 731da3c..8e55e84 100644
--- a/src/cff/cf2ft.h
+++ b/src/cff/cf2ft.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2FT_H__
-#define __CF2FT_H__
+#ifndef CF2FT_H_
+#define CF2FT_H_
 
 
 #include "cf2types.h"
@@ -99,18 +99,18 @@
 
   FT_LOCAL( CF2_Int )
   cf2_initGlobalRegionBuffer( CFF_Decoder*  decoder,
-                              CF2_UInt      idx,
+                              CF2_Int       subrNum,
                               CF2_Buffer    buf );
   FT_LOCAL( FT_Error )
   cf2_getSeacComponent( CFF_Decoder*  decoder,
-                        CF2_UInt      code,
+                        CF2_Int       code,
                         CF2_Buffer    buf );
   FT_LOCAL( void )
   cf2_freeSeacComponent( CFF_Decoder*  decoder,
                          CF2_Buffer    buf );
   FT_LOCAL( CF2_Int )
   cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
-                             CF2_UInt      idx,
+                             CF2_Int       subrNum,
                              CF2_Buffer    buf );
 
   FT_LOCAL( CF2_Fixed )
@@ -141,7 +141,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2FT_H__ */
+#endif /* CF2FT_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2glue.h b/src/cff/cf2glue.h
index a24da39..56a7c24 100644
--- a/src/cff/cf2glue.h
+++ b/src/cff/cf2glue.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2GLUE_H__
-#define __CF2GLUE_H__
+#ifndef CF2GLUE_H_
+#define CF2GLUE_H_
 
 
 /* common includes for other modules */
@@ -138,7 +138,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2GLUE_H__ */
+#endif /* CF2GLUE_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
index 81049f4..bbbe8e3 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -304,9 +304,6 @@
   cf2_hintmap_map( CF2_HintMap  hintmap,
                    CF2_Fixed    csCoord )
   {
-    FT_ASSERT( hintmap->isValid );  /* must call Build before Map */
-    FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
-
     if ( hintmap->count == 0 || ! hintmap->hinted )
     {
       /* there are no hints; use uniform scale and zero offset */
@@ -317,6 +314,7 @@
       /* start linear search from last hit */
       CF2_UInt  i = hintmap->lastIndex;
 
+      FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
 
       /* search up */
       while ( i < hintmap->count - 1                  &&
@@ -589,8 +587,9 @@
     }
 
     /* paired edges must be in proper order */
-    FT_ASSERT( !isPair                                         ||
-               topHintEdge->csCoord >= bottomHintEdge->csCoord );
+    if ( isPair                                         &&
+         topHintEdge->csCoord < bottomHintEdge->csCoord )
+      return;
 
     /* linear search to find index value of insertion point */
     indexInsert = 0;
@@ -699,10 +698,10 @@
 
     /* make room to insert */
     {
-      CF2_Int  iSrc = hintmap->count - 1;
-      CF2_Int  iDst = isPair ? hintmap->count + 1 : hintmap->count;
+      CF2_UInt  iSrc = hintmap->count - 1;
+      CF2_UInt  iDst = isPair ? hintmap->count + 1 : hintmap->count;
 
-      CF2_Int  count = hintmap->count - indexInsert;
+      CF2_UInt  count = hintmap->count - indexInsert;
 
 
       if ( iDst >= CF2_MAX_HINT_EDGES )
@@ -794,9 +793,12 @@
     maskPtr      = cf2_hintmask_getMaskPtr( &tempHintMask );
 
     /* use the hStem hints only, which are first in the mask */
-    /* TODO: compare this to cffhintmaskGetBitCount */
     bitCount = cf2_arrstack_size( hStemHintArray );
 
+    /* Defense-in-depth.  Should never return here. */
+    if ( bitCount > hintMask->bitCount )
+        return;
+
     /* synthetic embox hints get highest priority */
     if ( font->blues.doEmBoxHints )
     {
@@ -1691,7 +1693,8 @@
 
     if ( glyphpath->elemIsQueued )
     {
-      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+                 glyphpath->hintMap.count == 0              );
 
       cf2_glyphpath_pushPrevElem( glyphpath,
                                   &glyphpath->hintMap,
@@ -1777,7 +1780,8 @@
 
     if ( glyphpath->elemIsQueued )
     {
-      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+                 glyphpath->hintMap.count == 0              );
 
       cf2_glyphpath_pushPrevElem( glyphpath,
                                   &glyphpath->hintMap,
diff --git a/src/cff/cf2hints.h b/src/cff/cf2hints.h
index f25d91b..a898454 100644
--- a/src/cff/cf2hints.h
+++ b/src/cff/cf2hints.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2HINTS_H__
-#define __CF2HINTS_H__
+#ifndef CF2HINTS_H_
+#define CF2HINTS_H_
 
 
 FT_BEGIN_HEADER
@@ -220,7 +220,7 @@
 
     /* character space miter limit threshold */
     CF2_Fixed  miterLimit;
-    /* vertical/horzizontal snap distance in character space */
+    /* vertical/horizontal snap distance in character space */
     CF2_Fixed  snapThreshold;
 
     FT_Vector  offsetStart0;  /* first and second points of first */
@@ -283,7 +283,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2HINTS_H__ */
+#endif /* CF2HINTS_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
index 5610917..10e7b4b 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Adobe's CFF Interpreter (body).                                      */
 /*                                                                         */
-/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*  Copyright 2007-2014 Adobe Systems Incorporated.                        */
 /*                                                                         */
 /*  This software, and all works of authorship, whether in source or       */
 /*  object code form as indicated by the copyright notice(s) included      */
@@ -43,6 +43,7 @@
 #include "cf2font.h"
 #include "cf2stack.h"
 #include "cf2hints.h"
+#include "cf2intrp.h"
 
 #include "cf2error.h"
 
@@ -183,7 +184,7 @@
       return;
 
     FT_ASSERT( hintmask->byteCount > 0 );
-    FT_ASSERT( hintmask->byteCount <
+    FT_ASSERT( hintmask->byteCount <=
                  sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
 
     /* set mask to all ones */
@@ -292,7 +293,8 @@
     /* variable accumulates delta values from operand stack */
     CF2_Fixed  position = hintOffset;
 
-    if ( hasWidthArg && ! *haveWidth )
+
+    if ( hasWidthArg && !*haveWidth )
       *width = cf2_stack_getReal( opStack, 0 ) +
                  cf2_getNominalWidthX( font->decoder );
 
@@ -445,6 +447,8 @@
     CF2_Stack  opStack = NULL;
     FT_Byte    op1;                       /* first opcode byte */
 
+    CF2_F16Dot16  storage[CF2_STORAGE_SIZE];    /* for `put' and `get' */
+
     /* instruction limit; 20,000,000 matches Avalon */
     FT_UInt32  instructionLimit = 20000000UL;
 
@@ -465,6 +469,8 @@
     CF2_GlyphPathRec  glyphPath;
 
 
+    FT_ZERO( &storage );
+
     /* initialize the remaining objects */
     cf2_arrstack_init( &subrStack,
                        memory,
@@ -593,8 +599,11 @@
 
         /* never add hints after the mask is computed */
         if ( cf2_hintmask_isValid( &hintMask ) )
+        {
           FT_TRACE4(( "cf2_interpT2CharString:"
                       " invalid horizontal hint mask\n" ));
+          break;
+        }
 
         cf2_doStems( font,
                      opStack,
@@ -604,7 +613,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         break;
 
@@ -614,8 +623,11 @@
 
         /* never add hints after the mask is computed */
         if ( cf2_hintmask_isValid( &hintMask ) )
+        {
           FT_TRACE4(( "cf2_interpT2CharString:"
                       " invalid vertical hint mask\n" ));
+          break;
+        }
 
         cf2_doStems( font,
                      opStack,
@@ -625,7 +637,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         break;
 
@@ -639,7 +651,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curY += cf2_stack_popFixed( opStack );
 
@@ -739,7 +751,7 @@
       case cf2_cmdCALLGSUBR:
       case cf2_cmdCALLSUBR:
         {
-          CF2_UInt  subrIndex;
+          CF2_Int  subrNum;
 
 
           FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
@@ -754,19 +766,22 @@
 
           /* push our current CFF charstring region on subrStack */
           charstring = (CF2_Buffer)
-                         cf2_arrstack_getPointer( &subrStack,
-                                                  charstringIndex + 1 );
+                         cf2_arrstack_getPointer(
+                           &subrStack,
+                           (size_t)charstringIndex + 1 );
 
           /* set up the new CFF region and pointer */
-          subrIndex = cf2_stack_popInt( opStack );
+          subrNum = cf2_stack_popInt( opStack );
 
           switch ( op1 )
           {
           case cf2_cmdCALLGSUBR:
-            FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
+            FT_TRACE4(( " (idx %d, entering level %d)\n",
+                        subrNum + decoder->globals_bias,
+                        charstringIndex + 1 ));
 
             if ( cf2_initGlobalRegionBuffer( decoder,
-                                             subrIndex,
+                                             subrNum,
                                              charstring ) )
             {
               lastError = FT_THROW( Invalid_Glyph_Format );
@@ -776,10 +791,12 @@
 
           default:
             /* cf2_cmdCALLSUBR */
-            FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
+            FT_TRACE4(( " (idx %d, entering level %d)\n",
+                        subrNum + decoder->locals_bias,
+                        charstringIndex + 1 ));
 
             if ( cf2_initLocalRegionBuffer( decoder,
-                                            subrIndex,
+                                            subrNum,
                                             charstring ) )
             {
               lastError = FT_THROW( Invalid_Glyph_Format );
@@ -792,7 +809,7 @@
         continue; /* do not clear the stack */
 
       case cf2_cmdRETURN:
-        FT_TRACE4(( " return\n" ));
+        FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
 
         if ( charstringIndex < 1 )
         {
@@ -803,8 +820,9 @@
 
         /* restore position in previous charstring */
         charstring = (CF2_Buffer)
-                       cf2_arrstack_getPointer( &subrStack,
-                                                --charstringIndex );
+                       cf2_arrstack_getPointer(
+                         &subrStack,
+                         (CF2_UInt)--charstringIndex );
         continue;     /* do not clear the stack */
 
       case cf2_cmdESC:
@@ -820,84 +838,189 @@
 
             break;
 
-          /* TODO: should these operators be supported? */
-          case cf2_escAND: /* in spec */
-            FT_TRACE4(( " and\n" ));
+          case cf2_escAND:
+            {
+              CF2_F16Dot16  arg1;
+              CF2_F16Dot16  arg2;
 
-            CF2_FIXME;
-            break;
 
-          case cf2_escOR: /* in spec */
-            FT_TRACE4(( " or\n" ));
+              FT_TRACE4(( " and\n" ));
 
-            CF2_FIXME;
-            break;
+              arg2 = cf2_stack_popFixed( opStack );
+              arg1 = cf2_stack_popFixed( opStack );
 
-          case cf2_escNOT: /* in spec */
-            FT_TRACE4(( " not\n" ));
+              cf2_stack_pushInt( opStack, arg1 && arg2 );
+            }
+            continue; /* do not clear the stack */
 
-            CF2_FIXME;
-            break;
+          case cf2_escOR:
+            {
+              CF2_F16Dot16  arg1;
+              CF2_F16Dot16  arg2;
 
-          case cf2_escABS: /* in spec */
-            FT_TRACE4(( " abs\n" ));
 
-            CF2_FIXME;
-            break;
+              FT_TRACE4(( " or\n" ));
 
-          case cf2_escADD: /* in spec */
-            FT_TRACE4(( " add\n" ));
+              arg2 = cf2_stack_popFixed( opStack );
+              arg1 = cf2_stack_popFixed( opStack );
 
-            CF2_FIXME;
-            break;
+              cf2_stack_pushInt( opStack, arg1 || arg2 );
+            }
+            continue; /* do not clear the stack */
 
-          case cf2_escSUB: /* in spec */
-            FT_TRACE4(( " sub\n" ));
+          case cf2_escNOT:
+            {
+              CF2_F16Dot16  arg;
 
-            CF2_FIXME;
-            break;
 
-          case cf2_escDIV: /* in spec */
-            FT_TRACE4(( " div\n" ));
+              FT_TRACE4(( " not\n" ));
 
-            CF2_FIXME;
-            break;
+              arg = cf2_stack_popFixed( opStack );
 
-          case cf2_escNEG: /* in spec */
-            FT_TRACE4(( " neg\n" ));
+              cf2_stack_pushInt( opStack, !arg );
+            }
+            continue; /* do not clear the stack */
 
-            CF2_FIXME;
-            break;
+          case cf2_escABS:
+            {
+              CF2_F16Dot16  arg;
 
-          case cf2_escEQ: /* in spec */
-            FT_TRACE4(( " eq\n" ));
 
-            CF2_FIXME;
-            break;
+              FT_TRACE4(( " abs\n" ));
 
-          case cf2_escDROP: /* in spec */
+              arg = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escADD:
+            {
+              CF2_F16Dot16  summand1;
+              CF2_F16Dot16  summand2;
+
+
+              FT_TRACE4(( " add\n" ));
+
+              summand2 = cf2_stack_popFixed( opStack );
+              summand1 = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, summand1 + summand2 );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escSUB:
+            {
+              CF2_F16Dot16  minuend;
+              CF2_F16Dot16  subtrahend;
+
+
+              FT_TRACE4(( " sub\n" ));
+
+              subtrahend = cf2_stack_popFixed( opStack );
+              minuend    = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, minuend - subtrahend );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escDIV:
+            {
+              CF2_F16Dot16  dividend;
+              CF2_F16Dot16  divisor;
+
+
+              FT_TRACE4(( " div\n" ));
+
+              divisor  = cf2_stack_popFixed( opStack );
+              dividend = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escNEG:
+            {
+              CF2_F16Dot16  arg;
+
+
+              FT_TRACE4(( " neg\n" ));
+
+              arg = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, -arg );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escEQ:
+            {
+              CF2_F16Dot16  arg1;
+              CF2_F16Dot16  arg2;
+
+
+              FT_TRACE4(( " eq\n" ));
+
+              arg2 = cf2_stack_popFixed( opStack );
+              arg1 = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushInt( opStack, arg1 == arg2 );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escDROP:
             FT_TRACE4(( " drop\n" ));
 
-            CF2_FIXME;
-            break;
+            (void)cf2_stack_popFixed( opStack );
+            continue; /* do not clear the stack */
 
-          case cf2_escPUT: /* in spec */
-            FT_TRACE4(( " put\n" ));
+          case cf2_escPUT:
+            {
+              CF2_F16Dot16  val;
+              CF2_Int       idx;
 
-            CF2_FIXME;
-            break;
 
-          case cf2_escGET: /* in spec */
-            FT_TRACE4(( " get\n" ));
+              FT_TRACE4(( " put\n" ));
 
-            CF2_FIXME;
-            break;
+              idx = cf2_stack_popInt( opStack );
+              val = cf2_stack_popFixed( opStack );
 
-          case cf2_escIFELSE: /* in spec */
-            FT_TRACE4(( " ifelse\n" ));
+              if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                storage[idx] = val;
+            }
+            continue; /* do not clear the stack */
 
-            CF2_FIXME;
-            break;
+          case cf2_escGET:
+            {
+              CF2_Int  idx;
+
+
+              FT_TRACE4(( " get\n" ));
+
+              idx = cf2_stack_popInt( opStack );
+
+              if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                cf2_stack_pushFixed( opStack, storage[idx] );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escIFELSE:
+            {
+              CF2_F16Dot16  arg1;
+              CF2_F16Dot16  arg2;
+              CF2_F16Dot16  cond1;
+              CF2_F16Dot16  cond2;
+
+
+              FT_TRACE4(( " ifelse\n" ));
+
+              cond2 = cf2_stack_popFixed( opStack );
+              cond1 = cf2_stack_popFixed( opStack );
+              arg2  = cf2_stack_popFixed( opStack );
+              arg1  = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
+            }
+            continue; /* do not clear the stack */
 
           case cf2_escRANDOM: /* in spec */
             FT_TRACE4(( " random\n" ));
@@ -905,41 +1028,126 @@
             CF2_FIXME;
             break;
 
-          case cf2_escMUL: /* in spec */
-            FT_TRACE4(( " mul\n" ));
+          case cf2_escMUL:
+            {
+              CF2_F16Dot16  factor1;
+              CF2_F16Dot16  factor2;
 
-            CF2_FIXME;
-            break;
 
-          case cf2_escSQRT: /* in spec */
-            FT_TRACE4(( " sqrt\n" ));
+              FT_TRACE4(( " mul\n" ));
 
-            CF2_FIXME;
-            break;
+              factor2 = cf2_stack_popFixed( opStack );
+              factor1 = cf2_stack_popFixed( opStack );
 
-          case cf2_escDUP: /* in spec */
-            FT_TRACE4(( " dup\n" ));
+              cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
+            }
+            continue; /* do not clear the stack */
 
-            CF2_FIXME;
-            break;
+          case cf2_escSQRT:
+            {
+              CF2_F16Dot16  arg;
 
-          case cf2_escEXCH: /* in spec */
-            FT_TRACE4(( " exch\n" ));
 
-            CF2_FIXME;
-            break;
+              FT_TRACE4(( " sqrt\n" ));
 
-          case cf2_escINDEX: /* in spec */
-            FT_TRACE4(( " index\n" ));
+              arg = cf2_stack_popFixed( opStack );
+              if ( arg > 0 )
+              {
+                FT_Fixed  root = arg;
+                FT_Fixed  new_root;
 
-            CF2_FIXME;
-            break;
 
-          case cf2_escROLL: /* in spec */
-            FT_TRACE4(( " roll\n" ));
+                /* Babylonian method */
+                for (;;)
+                {
+                  new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
+                  if ( new_root == root )
+                    break;
+                  root = new_root;
+                }
+                arg = new_root;
+              }
+              else
+                arg = 0;
 
-            CF2_FIXME;
-            break;
+              cf2_stack_pushFixed( opStack, arg );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escDUP:
+            {
+              CF2_F16Dot16  arg;
+
+
+              FT_TRACE4(( " dup\n" ));
+
+              arg = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, arg );
+              cf2_stack_pushFixed( opStack, arg );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escEXCH:
+            {
+              CF2_F16Dot16  arg1;
+              CF2_F16Dot16  arg2;
+
+
+              FT_TRACE4(( " exch\n" ));
+
+              arg2 = cf2_stack_popFixed( opStack );
+              arg1 = cf2_stack_popFixed( opStack );
+
+              cf2_stack_pushFixed( opStack, arg2 );
+              cf2_stack_pushFixed( opStack, arg1 );
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escINDEX:
+            {
+              CF2_Int   idx;
+              CF2_UInt  size;
+
+
+              FT_TRACE4(( " index\n" ));
+
+              idx  = cf2_stack_popInt( opStack );
+              size = cf2_stack_count( opStack );
+
+              if ( size > 0 )
+              {
+                /* for `cf2_stack_getReal', index 0 is bottom of stack */
+                CF2_UInt  gr_idx;
+
+
+                if ( idx < 0 )
+                  gr_idx = size - 1;
+                else if ( (CF2_UInt)idx >= size )
+                  gr_idx = 0;
+                else
+                  gr_idx = size - 1 - (CF2_UInt)idx;
+
+                cf2_stack_pushFixed( opStack,
+                                     cf2_stack_getReal( opStack, gr_idx ) );
+              }
+            }
+            continue; /* do not clear the stack */
+
+          case cf2_escROLL:
+            {
+              CF2_Int  idx;
+              CF2_Int  count;
+
+
+              FT_TRACE4(( " roll\n" ));
+
+              idx   = cf2_stack_popInt( opStack );
+              count = cf2_stack_popInt( opStack );
+
+              cf2_stack_roll( opStack, count, idx );
+            }
+            continue; /* do not clear the stack */
 
           case cf2_escHFLEX:
             {
@@ -1072,7 +1280,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         /* close path if still open */
         cf2_glyphpath_closeOpenPath( &glyphPath );
@@ -1082,8 +1290,8 @@
           /* must be either 4 or 5 --                       */
           /* this is a (deprecated) implied `seac' operator */
 
-          CF2_UInt       achar;
-          CF2_UInt       bchar;
+          CF2_Int        achar;
+          CF2_Int        bchar;
           CF2_BufferRec  component;
           CF2_Fixed      dummyWidth;   /* ignore component width */
           FT_Error       error2;
@@ -1104,8 +1312,8 @@
           error2 = cf2_getSeacComponent( decoder, achar, &component );
           if ( error2 )
           {
-             lastError = error2;      /* pass FreeType error through */
-             goto exit;
+            lastError = error2;      /* pass FreeType error through */
+            goto exit;
           }
           cf2_interpT2CharString( font,
                                   &component,
@@ -1141,15 +1349,16 @@
         /* `cf2_hintmask_read' (which also traces the mask bytes) */
         FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
 
-        /* if there are arguments on the stack, there this is an */
-        /* implied cf2_cmdVSTEMHM                                */
-        if ( cf2_stack_count( opStack ) != 0 )
+        /* never add hints after the mask is computed */
+        if ( cf2_stack_count( opStack ) > 1    &&
+             cf2_hintmask_isValid( &hintMask ) )
         {
-          /* never add hints after the mask is computed */
-          if ( cf2_hintmask_isValid( &hintMask ) )
-            FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+          FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+          break;
         }
 
+        /* if there are arguments on the stack, there this is an */
+        /* implied cf2_cmdVSTEMHM                                */
         cf2_doStems( font,
                      opStack,
                      &vStemHintArray,
@@ -1158,7 +1367,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         if ( op1 == cf2_cmdHINTMASK )
         {
@@ -1217,7 +1426,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curY += cf2_stack_popFixed( opStack );
         curX += cf2_stack_popFixed( opStack );
@@ -1236,7 +1445,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curX += cf2_stack_popFixed( opStack );
 
@@ -1284,10 +1493,16 @@
 
       case cf2_cmdVVCURVETO:
         {
-          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  count, count1 = cf2_stack_count( opStack );
           CF2_UInt  index = 0;
 
 
+          /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+          /* we enforce it by clearing the second bit           */
+          /* (and sorting the stack indexing to suit)           */
+          count  = count1 & ~2U;
+          index += count1 - count;
+
           FT_TRACE4(( " vvcurveto\n" ));
 
           while ( index < count )
@@ -1323,10 +1538,16 @@
 
       case cf2_cmdHHCURVETO:
         {
-          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  count, count1 = cf2_stack_count( opStack );
           CF2_UInt  index = 0;
 
 
+          /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+          /* we enforce it by clearing the second bit           */
+          /* (and sorting the stack indexing to suit)           */
+          count  = count1 & ~2U;
+          index += count1 - count;
+
           FT_TRACE4(( " hhcurveto\n" ));
 
           while ( index < count )
@@ -1363,12 +1584,19 @@
       case cf2_cmdVHCURVETO:
       case cf2_cmdHVCURVETO:
         {
-          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  count, count1 = cf2_stack_count( opStack );
           CF2_UInt  index = 0;
 
           FT_Bool  alternate = op1 == cf2_cmdHVCURVETO;
 
 
+          /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
+          /* 8n+4, or 8n+5, we enforce it by clearing the     */
+          /* second bit                                       */
+          /* (and sorting the stack indexing to suit)         */
+          count  = count1 & ~2U;
+          index += count1 - count;
+
           FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
 
           while ( index < count )
@@ -1430,9 +1658,12 @@
         {
           CF2_Int  v;
 
+          CF2_Int  byte1 = cf2_buf_readByte( charstring );
+          CF2_Int  byte2 = cf2_buf_readByte( charstring );
 
-          v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
-                            cf2_buf_readByte( charstring )        );
+
+          v = (FT_Short)( ( byte1 << 8 ) |
+                            byte2        );
 
           FT_TRACE4(( " %d", v ));
 
@@ -1494,12 +1725,16 @@
           {
             CF2_Fixed  v;
 
+            FT_UInt32  byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
+            FT_UInt32  byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
+            FT_UInt32  byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
+            FT_UInt32  byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
 
-            v = (CF2_Fixed)
-                  ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
-                    ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
-                    ( (FT_UInt32)cf2_buf_readByte( charstring ) <<  8 ) |
-                      (FT_UInt32)cf2_buf_readByte( charstring )         );
+
+            v = (CF2_Fixed)( ( byte1 << 24 ) |
+                             ( byte2 << 16 ) |
+                             ( byte3 <<  8 ) |
+                               byte4         );
 
             FT_TRACE4(( " %.2f", v / 65536.0 ));
 
diff --git a/src/cff/cf2intrp.h b/src/cff/cf2intrp.h
index b5d8947..ec030e8 100644
--- a/src/cff/cf2intrp.h
+++ b/src/cff/cf2intrp.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2INTRP_H__
-#define __CF2INTRP_H__
+#ifndef CF2INTRP_H_
+#define CF2INTRP_H_
 
 
 #include "cf2ft.h"
@@ -77,7 +77,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2INTRP_H__ */
+#endif /* CF2INTRP_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2read.h b/src/cff/cf2read.h
index 7ef7c8c..b0b0db8 100644
--- a/src/cff/cf2read.h
+++ b/src/cff/cf2read.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2READ_H__
-#define __CF2READ_H__
+#ifndef CF2READ_H_
+#define CF2READ_H_
 
 
 FT_BEGIN_HEADER
@@ -62,7 +62,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2READ_H__ */
+#endif /* CF2READ_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2stack.c b/src/cff/cf2stack.c
index 8332b5d..8f3adb6 100644
--- a/src/cff/cf2stack.c
+++ b/src/cff/cf2stack.c
@@ -53,14 +53,14 @@
   cf2_stack_init( FT_Memory  memory,
                   FT_Error*  e )
   {
-    FT_Error  error = FT_Err_Ok;     /* for FT_QNEW */
+    FT_Error  error = FT_Err_Ok;     /* for FT_NEW */
 
     CF2_Stack  stack = NULL;
 
 
-    if ( !FT_QNEW( stack ) )
+    if ( !FT_NEW( stack ) )
     {
-      /* initialize the structure; FT_QNEW zeroes it */
+      /* initialize the structure; FT_NEW zeroes it */
       stack->memory = memory;
       stack->error  = e;
       stack->top    = &stack->buffer[0]; /* empty stack */
@@ -145,7 +145,7 @@
 
 
   /* Note: type mismatch is silently cast */
-  /* TODO: check this */
+  /* TODO: check this                     */
   FT_LOCAL_DEF( CF2_Fixed )
   cf2_stack_popFixed( CF2_Stack  stack )
   {
@@ -170,7 +170,7 @@
 
 
   /* Note: type mismatch is silently cast */
-  /* TODO: check this */
+  /* TODO: check this                     */
   FT_LOCAL_DEF( CF2_Fixed )
   cf2_stack_getReal( CF2_Stack  stack,
                      CF2_UInt   idx )
@@ -195,6 +195,86 @@
   }
 
 
+  FT_LOCAL( void )
+  cf2_stack_roll( CF2_Stack  stack,
+                  CF2_Int    count,
+                  CF2_Int    shift )
+  {
+    /* we initialize this variable to avoid compiler warnings */
+    CF2_StackNumber  last = { { 0 }, CF2_NumberInt };
+
+    CF2_Int  start_idx, idx, i;
+
+
+    if ( count < 2 )
+      return; /* nothing to do (values 0 and 1), or undefined value */
+
+    if ( (CF2_UInt)count > cf2_stack_count( stack ) )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Overflow );
+      return;
+    }
+
+    if ( shift < 0 )
+      shift = -( ( -shift ) % count );
+    else
+      shift %= count;
+
+    if ( shift == 0 )
+      return; /* nothing to do */
+
+    /* We use the following algorithm to do the rolling, */
+    /* which needs two temporary variables only.         */
+    /*                                                   */
+    /* Example:                                          */
+    /*                                                   */
+    /*   count = 8                                       */
+    /*   shift = 2                                       */
+    /*                                                   */
+    /*   stack indices before roll:  7 6 5 4 3 2 1 0     */
+    /*   stack indices after roll:   1 0 7 6 5 4 3 2     */
+    /*                                                   */
+    /* The value of index 0 gets moved to index 2, while */
+    /* the old value of index 2 gets moved to index 4,   */
+    /* and so on.  We thus have the following copying    */
+    /* chains for shift value 2.                         */
+    /*                                                   */
+    /*   0 -> 2 -> 4 -> 6 -> 0                           */
+    /*   1 -> 3 -> 5 -> 7 -> 1                           */
+    /*                                                   */
+    /* If `count' and `shift' are incommensurable, we    */
+    /* have a single chain only.  Otherwise, increase    */
+    /* the start index by 1 after the first chain, then  */
+    /* do the next chain until all elements in all       */
+    /* chains are handled.                               */
+
+    start_idx = -1;
+    idx       = -1;
+    for ( i = 0; i < count; i++ )
+    {
+      CF2_StackNumber  tmp;
+
+
+      if ( start_idx == idx )
+      {
+        start_idx++;
+        idx  = start_idx;
+        last = stack->buffer[idx];
+      }
+
+      idx += shift;
+      if ( idx >= count )
+        idx -= count;
+      else if ( idx < 0 )
+        idx += count;
+
+      tmp                = stack->buffer[idx];
+      stack->buffer[idx] = last;
+      last               = tmp;
+    }
+  }
+
+
   FT_LOCAL_DEF( void )
   cf2_stack_clear( CF2_Stack  stack )
   {
diff --git a/src/cff/cf2stack.h b/src/cff/cf2stack.h
index 7d6d196..e740a7a 100644
--- a/src/cff/cf2stack.h
+++ b/src/cff/cf2stack.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2STACK_H__
-#define __CF2STACK_H__
+#ifndef CF2STACK_H_
+#define CF2STACK_H_
 
 
 FT_BEGIN_HEADER
@@ -94,13 +94,18 @@
                      CF2_UInt   idx );
 
   FT_LOCAL( void )
+  cf2_stack_roll( CF2_Stack  stack,
+                  CF2_Int    count,
+                  CF2_Int    idx );
+
+  FT_LOCAL( void )
   cf2_stack_clear( CF2_Stack  stack );
 
 
 FT_END_HEADER
 
 
-#endif /* __CF2STACK_H__ */
+#endif /* CF2STACK_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2types.h b/src/cff/cf2types.h
index ac6a022..5b7e123 100644
--- a/src/cff/cf2types.h
+++ b/src/cff/cf2types.h
@@ -36,8 +36,8 @@
 /***************************************************************************/
 
 
-#ifndef __CF2TYPES_H__
-#define __CF2TYPES_H__
+#ifndef CF2TYPES_H_
+#define CF2TYPES_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -72,7 +72,7 @@
 FT_END_HEADER
 
 
-#endif /* __CF2TYPES_H__ */
+#endif /* CF2TYPES_H_ */
 
 
 /* END */
diff --git a/src/cff/cff.c b/src/cff/cff.c
index c3840b5..86ca1be 100644
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType OpenType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2013 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index f6e03c6..3ef4832 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF character mapping table (cmap) support (body).                   */
 /*                                                                         */
-/*  Copyright 2002-2007, 2010, 2013 by                                     */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -33,12 +33,15 @@
   /*************************************************************************/
 
   FT_CALLBACK_DEF( FT_Error )
-  cff_cmap_encoding_init( CFF_CMapStd  cmap )
+  cff_cmap_encoding_init( CFF_CMapStd  cmap,
+                          FT_Pointer   pointer )
   {
     TT_Face       face     = (TT_Face)FT_CMAP_FACE( cmap );
     CFF_Font      cff      = (CFF_Font)face->extra.data;
     CFF_Encoding  encoding = &cff->encoding;
 
+    FT_UNUSED( pointer );
+
 
     cmap->gids  = encoding->codes;
 
@@ -135,7 +138,8 @@
 
 
   FT_CALLBACK_DEF( FT_Error )
-  cff_cmap_unicode_init( PS_Unicodes  unicodes )
+  cff_cmap_unicode_init( PS_Unicodes  unicodes,
+                         FT_Pointer   pointer )
   {
     TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
     FT_Memory           memory  = FT_FACE_MEMORY( face );
@@ -143,6 +147,8 @@
     CFF_Charset         charset = &cff->charset;
     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
 
+    FT_UNUSED( pointer );
+
 
     /* can't build Unicode map for CID-keyed font */
     /* because we don't know glyph names.         */
diff --git a/src/cff/cffcmap.h b/src/cff/cffcmap.h
index 3f7f67b..23795d5 100644
--- a/src/cff/cffcmap.h
+++ b/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF character mapping table (cmap) support (specification).          */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2006 by                                          */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFCMAP_H__
-#define __CFFCMAP_H__
+#ifndef CFFCMAP_H_
+#define CFFCMAP_H_
 
 #include "cffobjs.h"
 
@@ -61,7 +61,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFCMAP_H__ */
+#endif /* CFFCMAP_H_ */
 
 
 /* END */
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index dde7d44..67bf09d 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2013 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -35,7 +35,7 @@
 #include "cfferrs.h"
 #include "cffpic.h"
 
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
 #include FT_SERVICE_GLYPH_DICT_H
 #include FT_SERVICE_PROPERTIES_H
 #include FT_CFF_DRIVER_H
@@ -64,11 +64,6 @@
   /*************************************************************************/
 
 
-#undef  PAIR_TAG
-#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
-                                     (FT_ULong)right        )
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -121,9 +116,6 @@
   }
 
 
-#undef PAIR_TAG
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -203,6 +195,68 @@
     FT_GlyphSlot  slot  = face->glyph;
 
 
+    if ( FT_IS_SFNT( face ) )
+    {
+      /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
+      /* it is no longer necessary that those values are identical to   */
+      /* the values in the `CFF' table                                  */
+
+      TT_Face   ttface = (TT_Face)face;
+      FT_Short  dummy;
+
+
+      if ( flags & FT_LOAD_VERTICAL_LAYOUT )
+      {
+        /* check whether we have data from the `vmtx' table at all; */
+        /* otherwise we extract the info from the CFF glyphstrings  */
+        /* (instead of synthesizing a global value using the `OS/2' */
+        /* table)                                                   */
+        if ( !ttface->vertical_info )
+          goto Missing_Table;
+
+        for ( nn = 0; nn < count; nn++ )
+        {
+          FT_UShort  ah;
+
+
+          ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+                                                       1,
+                                                       start + nn,
+                                                       &dummy,
+                                                       &ah );
+
+          FT_TRACE5(( "  idx %d: advance height %d font units\n",
+                      start + nn, ah ));
+          advances[nn] = ah;
+        }
+      }
+      else
+      {
+        /* check whether we have data from the `hmtx' table at all */
+        if ( !ttface->horizontal.number_Of_HMetrics )
+          goto Missing_Table;
+
+        for ( nn = 0; nn < count; nn++ )
+        {
+          FT_UShort  aw;
+
+
+          ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+                                                       0,
+                                                       start + nn,
+                                                       &dummy,
+                                                       &aw );
+
+          FT_TRACE5(( "  idx %d: advance width %d font units\n",
+                      start + nn, aw ));
+          advances[nn] = aw;
+        }
+      }
+
+      return error;
+    }
+
+  Missing_Table:
     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
 
     for ( nn = 0; nn < count; nn++ )
@@ -304,8 +358,8 @@
 
   FT_DEFINE_SERVICE_GLYPHDICTREC(
     cff_service_glyph_dict,
-    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
-    (FT_GlyphDict_NameIndexFunc)cff_get_name_index
+    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,      /* get_name   */
+    (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* name_index */
   )
 
 
@@ -352,7 +406,7 @@
       font_info->italic_angle        = dict->italic_angle;
       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
       font_info->underline_position  = (FT_Short)dict->underline_position;
-      font_info->underline_thickness = (FT_Short)dict->underline_thickness;
+      font_info->underline_thickness = (FT_UShort)dict->underline_thickness;
 
       cff->font_info = font_info;
     }
@@ -367,11 +421,13 @@
 
   FT_DEFINE_SERVICE_PSINFOREC(
     cff_service_ps_info,
-    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
-    (PS_GetFontExtraFunc)  NULL,
-    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
-    (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
-    (PS_GetFontValueFunc)  NULL         /* not implemented            */
+    (PS_GetFontInfoFunc)   cff_ps_get_font_info,    /* ps_get_font_info    */
+    (PS_GetFontExtraFunc)  NULL,                    /* ps_get_font_extra   */
+    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
+    /* unsupported with CFF fonts */
+    (PS_GetFontPrivateFunc)NULL,                    /* ps_get_font_private */
+    /* not implemented            */
+    (PS_GetFontValueFunc)  NULL                     /* ps_get_font_value   */
   )
 
 
@@ -383,16 +439,34 @@
   static const char*
   cff_get_ps_name( CFF_Face  face )
   {
-    CFF_Font  cff = (CFF_Font)face->extra.data;
+    CFF_Font      cff  = (CFF_Font)face->extra.data;
+    SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 
 
+    /* following the OpenType specification 1.7, we return the name stored */
+    /* in the `name' table for a CFF wrapped into an SFNT container        */
+
+    if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
+    {
+      FT_Library             library     = FT_FACE_LIBRARY( face );
+      FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
+      FT_Service_PsFontName  service     =
+        (FT_Service_PsFontName)ft_module_get_service(
+                                 sfnt_module,
+                                 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
+
+
+      if ( service && service->get_ps_font_name )
+        return service->get_ps_font_name( FT_FACE( face ) );
+    }
+
     return (const char*)cff->font_name;
   }
 
 
   FT_DEFINE_SERVICE_PSFONTNAMEREC(
     cff_service_ps_name,
-    (FT_PsName_GetFunc)cff_get_ps_name
+    (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
   )
 
 
@@ -439,7 +513,7 @@
 
   FT_DEFINE_SERVICE_TTCMAPSREC(
     cff_service_get_cmap_info,
-    (TT_CMap_Info_GetFunc)cff_get_cmap_info
+    (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
   )
 
 
@@ -569,9 +643,12 @@
 
   FT_DEFINE_SERVICE_CIDREC(
     cff_service_cid_info,
-    (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
-    (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
-    (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
+    (FT_CID_GetRegistryOrderingSupplementFunc)
+      cff_get_ros,                             /* get_ros                  */
+    (FT_CID_GetIsInternallyCIDKeyedFunc)
+      cff_get_is_cid,                          /* get_is_cid               */
+    (FT_CID_GetCIDFromGlyphIndexFunc)
+      cff_get_cid_from_glyph_index             /* get_cid_from_glyph_index */
   )
 
 
@@ -582,26 +659,62 @@
   static FT_Error
   cff_property_set( FT_Module    module,         /* CFF_Driver */
                     const char*  property_name,
-                    const void*  value )
+                    const void*  value,
+                    FT_Bool      value_is_string )
   {
     FT_Error    error  = FT_Err_Ok;
     CFF_Driver  driver = (CFF_Driver)module;
 
+#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+    FT_UNUSED( value_is_string );
+#endif
+
 
     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
     {
-      FT_Int*  darken_params = (FT_Int*)value;
+      FT_Int*  darken_params;
+      FT_Int   x1, y1, x2, y2, x3, y3, x4, y4;
 
-      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];
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      FT_Int   dp[8];
 
 
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
+        char*        ep;
+        int          i;
+
+
+        /* eight comma-separated numbers */
+        for ( i = 0; i < 7; i++ )
+        {
+          dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
+          if ( *ep != ',' || s == ep )
+            return FT_THROW( Invalid_Argument );
+
+          s = ep + 1;
+        }
+
+        dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
+        if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
+          return FT_THROW( Invalid_Argument );
+
+        darken_params = dp;
+      }
+      else
+#endif
+        darken_params = (FT_Int*)value;
+
+      x1 = darken_params[0];
+      y1 = darken_params[1];
+      x2 = darken_params[2];
+      y2 = darken_params[3];
+      x3 = darken_params[4];
+      y3 = darken_params[5];
+      x4 = darken_params[6];
+      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              ||
@@ -621,24 +734,62 @@
     }
     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
     {
-      FT_UInt*  hinting_engine = (FT_UInt*)value;
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
 
 
-#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
-      if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
-        error = FT_ERR( Unimplemented_Feature );
+        if ( !ft_strcmp( s, "adobe" ) )
+          driver->hinting_engine = FT_CFF_HINTING_ADOBE;
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+        else if ( !ft_strcmp( s, "freetype" ) )
+          driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
+#endif
+        else
+          return FT_THROW( Invalid_Argument );
+      }
       else
 #endif
-        driver->hinting_engine = *hinting_engine;
+      {
+        FT_UInt*  hinting_engine = (FT_UInt*)value;
 
-      return error;
+        if ( *hinting_engine == FT_CFF_HINTING_ADOBE
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+             || *hinting_engine == FT_CFF_HINTING_FREETYPE
+#endif
+           )
+          driver->hinting_engine = *hinting_engine;
+        else
+          error = FT_ERR( Unimplemented_Feature );
+
+        return error;
+      }
     }
     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
     {
-      FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s   = (const char*)value;
+        long         nsd = ft_strtol( s, NULL, 10 );
 
 
-      driver->no_stem_darkening = *no_stem_darkening;
+        if ( nsd == 0 )
+          driver->no_stem_darkening = 0;
+        else if ( nsd == 1 )
+          driver->no_stem_darkening = 1;
+        else
+          return FT_THROW( Invalid_Argument );
+      }
+      else
+#endif
+      {
+        FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+
+
+        driver->no_stem_darkening = *no_stem_darkening;
+      }
 
       return error;
     }
@@ -704,8 +855,8 @@
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     cff_service_properties,
-    (FT_Properties_SetFunc)cff_property_set,
-    (FT_Properties_GetFunc)cff_property_get )
+    (FT_Properties_SetFunc)cff_property_set,      /* set_property */
+    (FT_Properties_GetFunc)cff_property_get )     /* get_property */
 
 
   /*************************************************************************/
@@ -723,7 +874,7 @@
 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
   FT_DEFINE_SERVICEDESCREC7(
     cff_services,
-    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
+    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
@@ -734,7 +885,7 @@
 #else
   FT_DEFINE_SERVICEDESCREC6(
     cff_services,
-    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
+    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
@@ -753,7 +904,7 @@
     FT_Module_Interface  result;
 
 
-    /* CFF_SERVICES_GET derefers `library' in PIC mode */
+    /* CFF_SERVICES_GET dereferences `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     if ( !driver )
       return NULL;
@@ -793,9 +944,10 @@
   FT_DEFINE_DRIVER(
     cff_driver_class,
 
-      FT_MODULE_FONT_DRIVER       |
-      FT_MODULE_DRIVER_SCALABLE   |
-      FT_MODULE_DRIVER_HAS_HINTER,
+      FT_MODULE_FONT_DRIVER          |
+      FT_MODULE_DRIVER_SCALABLE      |
+      FT_MODULE_DRIVER_HAS_HINTER    |
+      FT_MODULE_DRIVER_HINTS_LIGHTLY,
 
       sizeof ( CFF_DriverRec ),
       "cff",
@@ -804,31 +956,29 @@
 
       0,   /* module-specific interface */
 
-      cff_driver_init,
-      cff_driver_done,
-      cff_get_interface,
+      cff_driver_init,          /* FT_Module_Constructor  module_init   */
+      cff_driver_done,          /* FT_Module_Destructor   module_done   */
+      cff_get_interface,        /* FT_Module_Requester    get_interface */
 
-    /* now the specific driver fields */
     sizeof ( TT_FaceRec ),
     sizeof ( CFF_SizeRec ),
     sizeof ( CFF_GlyphSlotRec ),
 
-    cff_face_init,
-    cff_face_done,
-    cff_size_init,
-    cff_size_done,
-    cff_slot_init,
-    cff_slot_done,
+    cff_face_init,              /* FT_Face_InitFunc  init_face */
+    cff_face_done,              /* FT_Face_DoneFunc  done_face */
+    cff_size_init,              /* FT_Size_InitFunc  init_size */
+    cff_size_done,              /* FT_Size_DoneFunc  done_size */
+    cff_slot_init,              /* FT_Slot_InitFunc  init_slot */
+    cff_slot_done,              /* FT_Slot_DoneFunc  done_slot */
 
-    cff_glyph_load,
+    cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
 
-    cff_get_kerning,
-    0,                       /* FT_Face_AttachFunc */
-    cff_get_advances,
+    cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
+    0,                          /* FT_Face_AttachFunc       attach_file  */
+    cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
 
-    cff_size_request,
-
-    CFF_SIZE_SELECT
+    cff_size_request,           /* FT_Size_RequestFunc  request_size */
+    CFF_SIZE_SELECT             /* FT_Size_SelectFunc   select_size  */
   )
 
 
diff --git a/src/cff/cffdrivr.h b/src/cff/cffdrivr.h
index 50e8138..d7b0598 100644
--- a/src/cff/cffdrivr.h
+++ b/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level OpenType driver interface (specification).                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFDRIVER_H__
-#define __CFFDRIVER_H__
+#ifndef CFFDRIVER_H_
+#define CFFDRIVER_H_
 
 
 #include <ft2build.h>
@@ -32,7 +32,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFDRIVER_H__ */
+#endif /* CFFDRIVER_H_ */
 
 
 /* END */
diff --git a/src/cff/cfferrs.h b/src/cff/cfferrs.h
index 801d73e..e7fc6eb 100644
--- a/src/cff/cfferrs.h
+++ b/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF error codes (specification only).                                */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,12 +22,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __CFFERRS_H__
-#define __CFFERRS_H__
+#ifndef CFFERRS_H_
+#define CFFERRS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  CFF_Err_
@@ -36,7 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __CFFERRS_H__ */
+#endif /* CFFERRS_H_ */
 
 
 /* END */
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index c8e9f91..4f375a6 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2013 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -273,8 +273,8 @@
       builder->current = &loader->current.outline;
       FT_GlyphLoader_Rewind( loader );
 
-      builder->hints_globals = 0;
-      builder->hints_funcs   = 0;
+      builder->hints_globals = NULL;
+      builder->hints_funcs   = NULL;
 
       if ( hinting && size )
       {
@@ -646,7 +646,7 @@
     for ( n = 0; n < cff->num_glyphs; n++ )
     {
       if ( cff->charset.sids[n] == glyph_sid )
-        return n;
+        return (FT_Int)n;
     }
 
     return -1;
@@ -672,7 +672,7 @@
 
 
       *pointer = (FT_Byte*)data.pointer;
-      *length = data.length;
+      *length  = (FT_ULong)data.length;
 
       return error;
     }
@@ -680,7 +680,7 @@
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
     {
-      CFF_Font  cff  = (CFF_Font)(face->extra.data);
+      CFF_Font  cff = (CFF_Font)(face->extra.data);
 
 
       return cff_index_access_element( &cff->charstrings_index, glyph_index,
@@ -703,11 +703,11 @@
     /* callback function.                                     */
     if ( face->root.internal->incremental_interface )
     {
-      FT_Data data;
+      FT_Data  data;
 
 
       data.pointer = *pointer;
-      data.length  = length;
+      data.length  = (FT_Int)length;
 
       face->root.internal->incremental_interface->funcs->free_glyph_data(
         face->root.internal->incremental_interface->object, &data );
@@ -819,14 +819,14 @@
     FT_GlyphLoader_Prepare( builder->loader );
 
     /* First load `bchar' in builder */
-    error = cff_get_glyph_data( face, bchar_index,
+    error = cff_get_glyph_data( face, (FT_UInt)bchar_index,
                                 &charstring, &charstring_len );
     if ( !error )
     {
       /* the seac operator must not be nested */
       decoder->seac = TRUE;
       error = cff_decoder_parse_charstrings( decoder, charstring,
-                                             charstring_len );
+                                             charstring_len, 0 );
       decoder->seac = FALSE;
 
       cff_free_glyph_data( face, &charstring, charstring_len );
@@ -849,14 +849,14 @@
     builder->pos_y = ady;
 
     /* Now load `achar' on top of the base outline. */
-    error = cff_get_glyph_data( face, achar_index,
+    error = cff_get_glyph_data( face, (FT_UInt)achar_index,
                                 &charstring, &charstring_len );
     if ( !error )
     {
       /* the seac operator must not be nested */
       decoder->seac = TRUE;
       error = cff_decoder_parse_charstrings( decoder, charstring,
-                                             charstring_len );
+                                             charstring_len, 0 );
       decoder->seac = FALSE;
 
       cff_free_glyph_data( face, &charstring, charstring_len );
@@ -895,13 +895,17 @@
   /*                                                                       */
   /*    charstring_len  :: The length in bytes of the charstring stream.   */
   /*                                                                       */
+  /*    in_dict         :: Set to 1 if function is called from top or      */
+  /*                       private DICT (needed for Multiple Master CFFs). */
+  /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
                                  FT_Byte*      charstring_base,
-                                 FT_ULong      charstring_len )
+                                 FT_ULong      charstring_len,
+                                 FT_Bool       in_dict )
   {
     FT_Error           error;
     CFF_Decoder_Zone*  zone;
@@ -913,6 +917,10 @@
     FT_Fixed*          stack;
     FT_Int             charstring_type =
                          decoder->cff->top_font.font_dict.charstring_type;
+    FT_UShort          num_designs =
+                         decoder->cff->top_font.font_dict.num_designs;
+    FT_UShort          num_axes =
+                         decoder->cff->top_font.font_dict.num_axes;
 
     T2_Hints_Funcs     hinter;
 
@@ -922,10 +930,10 @@
     decoder->read_width = 1;
 
     /* compute random seed from stack address of parameter */
-    seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
-                         (FT_PtrDist)(char*)&decoder           ^
-                         (FT_PtrDist)(char*)&charstring_base ) &
-                         FT_ULONG_MAX ) ;
+    seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed            ^
+                         (FT_Offset)(char*)&decoder         ^
+                         (FT_Offset)(char*)&charstring_base ) &
+                         FT_ULONG_MAX                         );
     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
     if ( seed == 0 )
       seed = 0x7384;
@@ -1241,6 +1249,44 @@
         if ( op == cff_op_unknown )
           continue;
 
+        /* in Multiple Master CFFs, T2 charstrings can appear in */
+        /* dictionaries, but some operators are prohibited       */
+        if ( in_dict )
+        {
+          switch ( op )
+          {
+          case cff_op_hstem:
+          case cff_op_vstem:
+          case cff_op_vmoveto:
+          case cff_op_rlineto:
+          case cff_op_hlineto:
+          case cff_op_vlineto:
+          case cff_op_rrcurveto:
+          case cff_op_hstemhm:
+          case cff_op_hintmask:
+          case cff_op_cntrmask:
+          case cff_op_rmoveto:
+          case cff_op_hmoveto:
+          case cff_op_vstemhm:
+          case cff_op_rcurveline:
+          case cff_op_rlinecurve:
+          case cff_op_vvcurveto:
+          case cff_op_hhcurveto:
+          case cff_op_vhcurveto:
+          case cff_op_hvcurveto:
+          case cff_op_hflex:
+          case cff_op_flex:
+          case cff_op_hflex1:
+          case cff_op_flex1:
+          case cff_op_callsubr:
+          case cff_op_callgsubr:
+            goto MM_Error;
+
+          default:
+            break;
+          }
+        }
+
         /* check arguments */
         req_args = cff_argument_counts[op];
         if ( req_args & CFF_COUNT_CHECK_WIDTH )
@@ -1278,7 +1324,9 @@
             case cff_op_endchar:
               /* If there is a width specified for endchar, we either have */
               /* 1 argument or 5 arguments.  We like to argue.             */
-              set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
+              set_width_ok = in_dict
+                               ? 0
+                               : ( ( num_args == 5 ) || ( num_args == 1 ) );
               break;
 
             default:
@@ -1373,12 +1421,12 @@
           {
             if ( op == cff_op_hintmask )
               hinter->hintmask( hinter->hints,
-                                builder->current->n_points,
-                                decoder->num_hints,
+                                (FT_UInt)builder->current->n_points,
+                                (FT_UInt)decoder->num_hints,
                                 ip );
             else
               hinter->counter( hinter->hints,
-                               decoder->num_hints,
+                               (FT_UInt)decoder->num_hints,
                                ip );
           }
 
@@ -1971,6 +2019,10 @@
             return error;
 
         case cff_op_endchar:
+          /* in dictionaries, `endchar' simply indicates end of data */
+          if ( in_dict )
+            return error;
+
           FT_TRACE4(( " endchar\n" ));
 
           /* We are going to emulate the seac operator. */
@@ -1989,23 +2041,22 @@
           }
           else
           {
-            if ( !error )
-              error = FT_Err_Ok;
-
             cff_builder_close_contour( builder );
 
             /* close hints recording session */
             if ( hinter )
             {
               if ( hinter->close( hinter->hints,
-                                  builder->current->n_points ) )
+                                  (FT_UInt)builder->current->n_points ) )
                 goto Syntax_Error;
 
               /* apply hints to the loaded glyph outline now */
-              hinter->apply( hinter->hints,
-                             builder->current,
-                             (PSH_Globals)builder->hints_globals,
-                             decoder->hint_mode );
+              error = hinter->apply( hinter->hints,
+                                     builder->current,
+                                     (PSH_Globals)builder->hints_globals,
+                                     decoder->hint_mode );
+              if ( error )
+                goto Fail;
             }
 
             /* add current outline to the glyph slot */
@@ -2083,15 +2134,14 @@
 
           if ( args[0] > 0 )
           {
-            FT_Int    count = 9;
-            FT_Fixed  root  = args[0];
+            FT_Fixed  root = args[0];
             FT_Fixed  new_root;
 
 
             for (;;)
             {
               new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
-              if ( new_root == root || count <= 0 )
+              if ( new_root == root )
                 break;
               root = new_root;
             }
@@ -2200,6 +2250,10 @@
 
             FT_TRACE4(( " put\n" ));
 
+            /* the Type2 specification before version 16-March-2000 */
+            /* didn't give a hard-coded size limit of the temporary */
+            /* storage array; instead, an argument of the           */
+            /* `MultipleMaster' operator set the size               */
             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
               decoder->buildchar[idx] = val;
           }
@@ -2222,14 +2276,68 @@
           break;
 
         case cff_op_store:
-          FT_TRACE4(( " store\n"));
+          /* this operator was removed from the Type2 specification */
+          /* in version 16-March-2000                               */
 
-          goto Unimplemented;
+          /* since we currently don't handle interpolation of multiple */
+          /* master fonts, this is a no-op                             */
+          FT_TRACE4(( " store\n"));
+          break;
 
         case cff_op_load:
-          FT_TRACE4(( " load\n" ));
+          /* this operator was removed from the Type2 specification */
+          /* in version 16-March-2000                               */
+          {
+            FT_Int  reg_idx = (FT_Int)args[0];
+            FT_Int  idx     = (FT_Int)args[1];
+            FT_Int  count   = (FT_Int)args[2];
 
-          goto Unimplemented;
+
+            FT_TRACE4(( " load\n" ));
+
+            /* since we currently don't handle interpolation of multiple */
+            /* master fonts, we store a vector [1 0 0 ...] in the        */
+            /* temporary storage array regardless of the Registry index  */
+            if ( reg_idx >= 0 && reg_idx <= 2             &&
+                 idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
+                 count >= 0 && count <= num_axes          )
+            {
+              FT_Int  end, i;
+
+
+              end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
+
+              if ( idx < end )
+                decoder->buildchar[idx] = 1 << 16;
+
+              for ( i = idx + 1; i < end; i++ )
+                decoder->buildchar[i] = 0;
+            }
+          }
+          break;
+
+        case cff_op_blend:
+          /* this operator was removed from the Type2 specification */
+          /* in version 16-March-2000                               */
+          {
+            FT_Int  num_results = (FT_Int)( args[0] >> 16 );
+
+
+            FT_TRACE4(( " blend\n" ));
+
+            if ( num_results < 0 )
+              goto Syntax_Error;
+
+            if ( num_results * (FT_Int)num_designs > num_args )
+              goto Stack_Underflow;
+
+            /* since we currently don't handle interpolation of multiple */
+            /* master fonts, return the `num_results' values of the      */
+            /* first master                                              */
+            args     -= num_results * ( num_designs - 1 );
+            num_args -= num_results * ( num_designs - 1 );
+          }
+          break;
 
         case cff_op_dotsection:
           /* this operator is deprecated and ignored by the parser */
@@ -2359,11 +2467,23 @@
           }
           break;
 
-        case cff_op_eq:
+        case cff_op_not:
           {
             FT_Fixed  cond = !args[0];
 
 
+            FT_TRACE4(( " not\n" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case cff_op_eq:
+          {
+            FT_Fixed  cond = args[0] == args[1];
+
+
             FT_TRACE4(( " eq\n" ));
 
             args[0] = cond ? 0x10000L : 0;
@@ -2390,7 +2510,9 @@
                                       decoder->locals_bias );
 
 
-            FT_TRACE4(( " callsubr(%d)\n", idx ));
+            FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
+                        idx,
+                        zone - decoder->zones + 1 ));
 
             if ( idx >= decoder->num_locals )
             {
@@ -2432,7 +2554,9 @@
                                       decoder->globals_bias );
 
 
-            FT_TRACE4(( " callgsubr(%d)\n", idx ));
+            FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
+                        idx,
+                        zone - decoder->zones + 1 ));
 
             if ( idx >= decoder->num_globals )
             {
@@ -2469,7 +2593,8 @@
           break;
 
         case cff_op_return:
-          FT_TRACE4(( " return\n" ));
+          FT_TRACE4(( " return (leaving level %d)\n",
+                      decoder->zone - decoder->zones ));
 
           if ( decoder->zone <= decoder->zones )
           {
@@ -2485,7 +2610,6 @@
           break;
 
         default:
-        Unimplemented:
           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
           if ( ip[-1] == 12 )
@@ -2509,6 +2633,11 @@
   Fail:
     return error;
 
+  MM_Error:
+    FT_TRACE4(( "cff_decoder_parse_charstrings:"
+                " invalid opcode found in top DICT charstring\n"));
+    return FT_THROW( Invalid_File_Format );
+
   Syntax_Error:
     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
     return FT_THROW( Invalid_File_Format );
@@ -2582,7 +2711,8 @@
         if ( !error )
           error = cff_decoder_parse_charstrings( &decoder,
                                                  charstring,
-                                                 charstring_len );
+                                                 charstring_len,
+                                                 0 );
 
         cff_free_glyph_data( face, &charstring, &charstring_len );
       }
@@ -2670,7 +2800,7 @@
         error = sfnt->load_sbit_image( face,
                                        size->strike_index,
                                        glyph_index,
-                                       (FT_Int)load_flags,
+                                       (FT_UInt)load_flags,
                                        stream,
                                        &glyph->root.bitmap,
                                        &metrics );
@@ -2711,23 +2841,23 @@
 
           /* compute linear advance widths */
 
-          ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
-                                                     glyph_index,
-                                                     &dummy,
-                                                     &advance );
+          (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+                                                           glyph_index,
+                                                           &dummy,
+                                                           &advance );
           glyph->root.linearHoriAdvance = advance;
 
           has_vertical_info = FT_BOOL(
                                 face->vertical_info                   &&
                                 face->vertical.number_Of_VMetrics > 0 );
 
-          /* get the vertical metrics from the vtmx table if we have one */
+          /* get the vertical metrics from the vmtx table if we have one */
           if ( has_vertical_info )
           {
-            ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
-                                                       glyph_index,
-                                                       &dummy,
-                                                       &advance );
+            (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
+                                                             glyph_index,
+                                                             &dummy,
+                                                             &advance );
             glyph->root.linearVertAdvance = advance;
           }
           else
@@ -2758,16 +2888,16 @@
     /* this scaling is only relevant if the PS hinter isn't active */
     if ( cff->num_subfonts )
     {
-      FT_ULong  top_upm, sub_upm;
-      FT_Byte   fd_index = cff_fd_select_get( &cff->fd_select,
-                                              glyph_index );
+      FT_Long  top_upm, sub_upm;
+      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select,
+                                             glyph_index );
 
 
       if ( fd_index >= cff->num_subfonts )
         fd_index = (FT_Byte)( cff->num_subfonts - 1 );
 
-      top_upm = cff->top_font.font_dict.units_per_em;
-      sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
+      top_upm = (FT_Long)cff->top_font.font_dict.units_per_em;
+      sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em;
 
 
       font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
@@ -2812,6 +2942,7 @@
       cff_decoder_init( &decoder, face, size, glyph, hinting,
                         FT_LOAD_TARGET_MODE( load_flags ) );
 
+      /* this is for pure CFFs */
       if ( load_flags & FT_LOAD_ADVANCE_ONLY )
         decoder.width_only = TRUE;
 
@@ -2833,7 +2964,8 @@
       if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
         error = cff_decoder_parse_charstrings( &decoder,
                                                charstring,
-                                               charstring_len );
+                                               charstring_len,
+                                               0 );
       else
 #endif
       {
@@ -2868,7 +3000,7 @@
       /* fonts.                                                       */
       if ( face->root.internal->incremental_interface )
       {
-        glyph->root.control_data = 0;
+        glyph->root.control_data = NULL;
         glyph->root.control_len = 0;
       }
       else
@@ -2885,7 +3017,7 @@
         {
           glyph->root.control_data = csindex->bytes +
                                      csindex->offsets[glyph_index] - 1;
-          glyph->root.control_len  = charstring_len;
+          glyph->root.control_len  = (FT_Long)charstring_len;
         }
       }
 
@@ -2945,19 +3077,36 @@
       {
         FT_BBox            cbox;
         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
-        FT_Vector          advance;
         FT_Bool            has_vertical_info;
 
 
-        /* copy the _unscaled_ advance width */
-        metrics->horiAdvance                    = decoder.glyph_width;
-        glyph->root.linearHoriAdvance           = decoder.glyph_width;
+        if ( face->horizontal.number_Of_HMetrics )
+        {
+          FT_Short   horiBearingX = 0;
+          FT_UShort  horiAdvance  = 0;
+
+
+          ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+                                                     glyph_index,
+                                                     &horiBearingX,
+                                                     &horiAdvance );
+          metrics->horiAdvance          = horiAdvance;
+          metrics->horiBearingX         = horiBearingX;
+          glyph->root.linearHoriAdvance = horiAdvance;
+        }
+        else
+        {
+          /* copy the _unscaled_ advance width */
+          metrics->horiAdvance          = decoder.glyph_width;
+          glyph->root.linearHoriAdvance = decoder.glyph_width;
+        }
+
         glyph->root.internal->glyph_transformed = 0;
 
         has_vertical_info = FT_BOOL( face->vertical_info                   &&
                                      face->vertical.number_Of_VMetrics > 0 );
 
-        /* get the vertical metrics from the vtmx table if we have one */
+        /* get the vertical metrics from the vmtx table if we have one */
         if ( has_vertical_info )
         {
           FT_Short   vertBearingY = 0;
@@ -2992,26 +3141,27 @@
 
         glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
 
-        if ( !( font_matrix.xx == 0x10000L &&
-                font_matrix.yy == 0x10000L &&
-                font_matrix.xy == 0        &&
-                font_matrix.yx == 0        ) )
+        /* apply the font matrix, if any */
+        if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
+             font_matrix.xy != 0        || font_matrix.yx != 0        )
+        {
           FT_Outline_Transform( &glyph->root.outline, &font_matrix );
 
-        if ( !( font_offset.x == 0 &&
-                font_offset.y == 0 ) )
+          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
+                                            font_matrix.xx );
+          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
+                                            font_matrix.yy );
+        }
+
+        if ( font_offset.x || font_offset.y )
+        {
           FT_Outline_Translate( &glyph->root.outline,
-                                font_offset.x, font_offset.y );
+                                font_offset.x,
+                                font_offset.y );
 
-        advance.x = metrics->horiAdvance;
-        advance.y = 0;
-        FT_Vector_Transform( &advance, &font_matrix );
-        metrics->horiAdvance = advance.x + font_offset.x;
-
-        advance.x = 0;
-        advance.y = metrics->vertAdvance;
-        FT_Vector_Transform( &advance, &font_matrix );
-        metrics->vertAdvance = advance.y + font_offset.y;
+          metrics->horiAdvance += font_offset.x;
+          metrics->vertAdvance += font_offset.y;
+        }
 
         if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
         {
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 41df7db..b875fbe 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2009, 2013 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFGLOAD_H__
-#define __CFFGLOAD_H__
+#ifndef CFFGLOAD_H_
+#define CFFGLOAD_H_
 
 
 #include <ft2build.h>
@@ -29,7 +29,12 @@
 
 
 #define CFF_MAX_OPERANDS        48
-#define CFF_MAX_SUBRS_CALLS     32
+#define CFF_MAX_SUBRS_CALLS     16  /* maximum subroutine nesting;         */
+                                    /* only 10 are allowed but there exist */
+                                    /* fonts like `HiraKakuProN-W3.ttf'    */
+                                    /* (Hiragino Kaku Gothic ProN W3;      */
+                                    /* 8.2d6e1; 2014-12-19) that exceed    */
+                                    /* this limit                          */
 #define CFF_MAX_TRANS_ELEMENTS  32
 
 
@@ -222,7 +227,8 @@
   FT_LOCAL( FT_Error )
   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
                                  FT_Byte*      charstring_base,
-                                 FT_ULong      charstring_len );
+                                 FT_ULong      charstring_len,
+                                 FT_Bool       in_dict );
 #endif
 
   FT_LOCAL( FT_Error )
@@ -234,7 +240,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFGLOAD_H__ */
+#endif /* CFFGLOAD_H_ */
 
 
 /* END */
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index d9bec59..470fa82 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2014 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -357,7 +357,7 @@
 
       case 3:
         for ( ; p < p_end; p += 3, poff++ )
-          poff[0] = FT_PEEK_OFF3( p );
+          poff[0] = FT_PEEK_UOFF3( p );
         break;
 
       default:
@@ -382,13 +382,15 @@
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table,
-                          FT_Byte**   pool )
+                          FT_Byte**   pool,
+                          FT_ULong*   pool_size )
   {
     FT_Error   error     = FT_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
 
     FT_Byte**  t         = NULL;
     FT_Byte*   new_bytes = NULL;
+    FT_ULong   new_size;
 
 
     *table = NULL;
@@ -400,10 +402,11 @@
         goto Exit;
     }
 
-    if ( idx->count > 0                                        &&
-         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
-         ( !pool || !FT_ALLOC( new_bytes,
-                               idx->data_size + idx->count ) ) )
+    new_size = idx->data_size + idx->count;
+
+    if ( idx->count > 0                                &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )            &&
+         ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
     {
       FT_ULong  n, cur_offset;
       FT_ULong  extra = 0;
@@ -459,6 +462,8 @@
 
       if ( pool )
         *pool = new_bytes;
+      if ( pool_size )
+        *pool_size = new_size;
     }
 
   Exit:
@@ -501,8 +506,8 @@
           {
             element++;
             off2 = cff_index_read_offset( idx, &error );
-          }
-          while ( off2 == 0 && element < idx->count );
+
+          } while ( off2 == 0 && element < idx->count );
         }
       }
       else   /* use offsets table */
@@ -597,7 +602,8 @@
 
     if ( !FT_ALLOC( name, byte_len + 1 ) )
     {
-      FT_MEM_COPY( name, bytes, byte_len );
+      if ( byte_len )
+        FT_MEM_COPY( name, bytes, byte_len );
       name[byte_len] = 0;
     }
     cff_index_forget_element( idx, &bytes );
@@ -809,7 +815,7 @@
     /* When multiple GIDs map to the same CID, we choose the lowest */
     /* GID.  This is not described in any spec, but it matches the  */
     /* behaviour of recent Acroread versions.                       */
-    for ( j = num_glyphs - 1; j >= 0 ; j-- )
+    for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
       charset->cids[charset->sids[j]] = (FT_UShort)j;
 
     charset->max_cid    = max_cid;
@@ -871,8 +877,8 @@
     FT_UShort  glyph_sid;
 
 
-    /* If the the offset is greater than 2, we have to parse the */
-    /* charset table.                                            */
+    /* If the offset is greater than 2, we have to parse the charset */
+    /* table.                                                        */
     if ( offset > 2 )
     {
       FT_UInt  j;
@@ -1316,7 +1322,12 @@
     CFF_Private      priv = &font->private_dict;
 
 
-    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
+    cff_parser_init( &parser,
+                     CFF_CODE_TOPDICT,
+                     &font->font_dict,
+                     library,
+                     0,
+                     0 );
 
     /* set defaults */
     FT_MEM_ZERO( top, sizeof ( *top ) );
@@ -1370,7 +1381,12 @@
       priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
       priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
 
-      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
+      cff_parser_init( &parser,
+                       CFF_CODE_PRIVATE,
+                       priv,
+                       library,
+                       top->num_designs,
+                       top->num_axes );
 
       if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
            FT_FRAME_ENTER( font->font_dict.private_size )                 )
@@ -1400,7 +1416,7 @@
         goto Exit;
 
       error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs, NULL );
+                                      &font->local_subrs, NULL, NULL );
       if ( error )
         goto Exit;
     }
@@ -1447,7 +1463,7 @@
     FT_ULong         base_offset;
     CFF_FontRecDict  dict;
     CFF_IndexRec     string_index;
-    FT_Int           subfont_index;
+    FT_UInt          subfont_index;
 
 
     FT_ZERO( font );
@@ -1478,16 +1494,17 @@
 
     /* read the name, top dict, string and global subrs index */
     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &string_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_get_pointers( &string_index,
                                                &font->strings,
-                                               &font->string_pool ) ) )
+                                               &font->string_pool,
+                                               &font->string_pool_size ) ) )
       goto Exit;
 
     font->num_strings = string_index.count;
@@ -1495,9 +1512,9 @@
     if ( pure_cff )
     {
       /* well, we don't really forget the `disabled' fonts... */
-      subfont_index = face_index;
+      subfont_index = (FT_UInt)( face_index & 0xFFFF );
 
-      if ( subfont_index >= (FT_Int)font->name_index.count )
+      if ( face_index > 0 && subfont_index >= font->name_index.count )
       {
         FT_ERROR(( "cff_font_load:"
                    " invalid subfont index for pure CFF font (%d)\n",
@@ -1614,7 +1631,7 @@
     font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs, NULL );
+                                    &font->global_subrs, NULL, NULL );
 
     if ( error )
       goto Exit;
diff --git a/src/cff/cffload.h b/src/cff/cffload.h
index 8049619..1dd07ba 100644
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType & CFF data/program tables loader (specification).           */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 by                   */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFLOAD_H__
-#define __CFFLOAD_H__
+#ifndef CFFLOAD_H_
+#define CFFLOAD_H_
 
 
 #include <ft2build.h>
@@ -77,7 +77,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFLOAD_H__ */
+#endif /* CFFLOAD_H_ */
 
 
 /* END */
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index cac4ac2..0f07696 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2013 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -226,8 +226,8 @@
       CFF_Font      font     = (CFF_Font)face->extra.data;
       CFF_Internal  internal = (CFF_Internal)size->internal;
 
-      FT_ULong  top_upm  = font->top_font.font_dict.units_per_em;
-      FT_UInt   i;
+      FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
+      FT_UInt  i;
 
 
       funcs->set_scale( internal->topfont,
@@ -237,7 +237,7 @@
       for ( i = font->num_subfonts; i > 0; i-- )
       {
         CFF_SubFont  sub     = font->subfonts[i - 1];
-        FT_ULong     sub_upm = sub->font_dict.units_per_em;
+        FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
         FT_Pos       x_scale, y_scale;
 
 
@@ -298,8 +298,8 @@
       CFF_Font      font     = (CFF_Font)cffface->extra.data;
       CFF_Internal  internal = (CFF_Internal)size->internal;
 
-      FT_ULong  top_upm  = font->top_font.font_dict.units_per_em;
-      FT_UInt   i;
+      FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
+      FT_UInt  i;
 
 
       funcs->set_scale( internal->topfont,
@@ -309,7 +309,7 @@
       for ( i = font->num_subfonts; i > 0; i-- )
       {
         CFF_SubFont  sub     = font->subfonts[i - 1];
-        FT_ULong     sub_upm = sub->font_dict.units_per_em;
+        FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
         FT_Pos       x_scale, y_scale;
 
 
@@ -342,7 +342,7 @@
   FT_LOCAL_DEF( void )
   cff_slot_done( FT_GlyphSlot  slot )
   {
-    slot->internal->glyph_hints = 0;
+    slot->internal->glyph_hints = NULL;
   }
 
 
@@ -583,16 +583,24 @@
       if ( error )
         goto Exit;
 
+      /* if we are performing a simple font format check, exit immediately */
+      /* (this is here for pure CFF)                                       */
+      if ( face_index < 0 )
+      {
+        cffface->num_faces = (FT_Long)cff->num_faces;
+        return FT_Err_Ok;
+      }
+
       cff->pshinter = pshinter;
       cff->psnames  = psnames;
 
-      cffface->face_index = face_index;
+      cffface->face_index = face_index & 0xFFFF;
 
       /* Complement the root flags with some interesting information. */
       /* Note that this is only necessary for pure CFF and CEF fonts; */
       /* SFNT based fonts use the `name' table instead.               */
 
-      cffface->num_glyphs = cff->num_glyphs;
+      cffface->num_glyphs = (FT_Long)cff->num_glyphs;
 
       dict = &cff->top_font.font_dict;
 
@@ -617,11 +625,44 @@
         FT_TRACE4(( "SIDs\n" ));
 
         /* dump string index, including default strings for convenience */
-        for ( idx = 0; idx < cff->num_strings + 390; idx++ )
+        for ( idx = 0; idx <= 390; idx++ )
         {
           s = cff_index_get_sid_string( cff, idx );
           if ( s )
-            FT_TRACE4(("  %5d %s\n", idx, s ));
+            FT_TRACE4(( "  %5d %s\n", idx, s ));
+        }
+
+        /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
+        /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
+        /* which may contain NULL bytes in the middle of the data, too. */
+        /* We thus access `cff->strings' directly.                      */
+        for ( idx = 1; idx < cff->num_strings; idx++ )
+        {
+          FT_Byte*    s1    = cff->strings[idx - 1];
+          FT_Byte*    s2    = cff->strings[idx];
+          FT_PtrDist  s1len = s2 - s1 - 1; /* without the final NULL byte */
+          FT_PtrDist  l;
+
+
+          FT_TRACE4(( "  %5d ", idx + 390 ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
+        }
+
+        /* print last element */
+        if ( cff->num_strings )
+        {
+          FT_Byte*    s1    = cff->strings[cff->num_strings - 1];
+          FT_Byte*    s2    = cff->string_pool + cff->string_pool_size;
+          FT_PtrDist  s1len = s2 - s1 - 1;
+          FT_PtrDist  l;
+
+
+          FT_TRACE4(( "  %5d ", cff->num_strings + 390 ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
         }
       }
 #endif /* FT_DEBUG_LEVEL_TRACE */
@@ -629,10 +670,11 @@
       if ( !dict->has_font_matrix )
         dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
 
-      /* Normalize the font matrix so that `matrix->xx' is 1; the */
-      /* scaling is done with `units_per_em' then (at this point, */
-      /* it already contains the scaling factor, but without      */
-      /* normalization of the matrix).                            */
+      /* Normalize the font matrix so that `matrix->yy' is 1; if  */
+      /* it is zero, we use `matrix->yx' instead.  The scaling is */
+      /* done with `units_per_em' then (at this point, it already */
+      /* contains the scaling factor, but without normalization   */
+      /* of the matrix).                                          */
       /*                                                          */
       /* Note that the offsets must be expressed in integer font  */
       /* units.                                                   */
@@ -641,12 +683,15 @@
         FT_Matrix*  matrix = &dict->font_matrix;
         FT_Vector*  offset = &dict->font_offset;
         FT_ULong*   upm    = &dict->units_per_em;
-        FT_Fixed    temp   = FT_ABS( matrix->yy );
+        FT_Fixed    temp;
 
 
+        temp = matrix->yy ? FT_ABS( matrix->yy )
+                          : FT_ABS( matrix->yx );
+
         if ( temp != 0x10000L )
         {
-          *upm = FT_DivFix( *upm, temp );
+          *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
 
           matrix->xx = FT_DivFix( matrix->xx, temp );
           matrix->yx = FT_DivFix( matrix->yx, temp );
@@ -682,7 +727,8 @@
           if ( top->has_font_matrix )
           {
             if ( top->units_per_em > 1 && sub->units_per_em > 1 )
-              scaling = FT_MIN( top->units_per_em, sub->units_per_em );
+              scaling = (FT_Long)FT_MIN( top->units_per_em,
+                                         sub->units_per_em );
             else
               scaling = 1;
 
@@ -693,9 +739,10 @@
                                         &top->font_matrix,
                                         scaling );
 
-            sub->units_per_em = FT_MulDiv( sub->units_per_em,
-                                           top->units_per_em,
-                                           scaling );
+            sub->units_per_em = (FT_ULong)
+                                  FT_MulDiv( (FT_Long)sub->units_per_em,
+                                             (FT_Long)top->units_per_em,
+                                             scaling );
           }
         }
         else
@@ -709,11 +756,14 @@
         matrix = &sub->font_matrix;
         offset = &sub->font_offset;
         upm    = &sub->units_per_em;
-        temp   = FT_ABS( matrix->yy );
+
+        temp = matrix->yy ? FT_ABS( matrix->yy )
+                          : FT_ABS( matrix->yx );
+
 
         if ( temp != 0x10000L )
         {
-          *upm = FT_DivFix( *upm, temp );
+          *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
 
           matrix->xx = FT_DivFix( matrix->xx, temp );
           matrix->yx = FT_DivFix( matrix->yx, temp );
@@ -733,13 +783,13 @@
 
 
         /* set up num_faces */
-        cffface->num_faces = cff->num_faces;
+        cffface->num_faces = (FT_Long)cff->num_faces;
 
         /* compute number of glyphs */
         if ( dict->cid_registry != 0xFFFFU )
-          cffface->num_glyphs = cff->charset.max_cid + 1;
+          cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 );
         else
-          cffface->num_glyphs = cff->charstrings_index.count;
+          cffface->num_glyphs = (FT_Long)cff->charstrings_index.count;
 
         /* set global bbox, as well as EM size */
         cffface->bbox.xMin =   dict->font_bbox.xMin            >> 16;
@@ -763,7 +813,9 @@
           (FT_Short)( dict->underline_thickness >> 16 );
 
         /* retrieve font family & style name */
-        cffface->family_name = cff_index_get_name( cff, face_index );
+        cffface->family_name = cff_index_get_name(
+                                 cff,
+                                 (FT_UInt)( face_index & 0xFFFF ) );
         if ( cffface->family_name )
         {
           char*  full   = cff_index_get_sid_string( cff,
@@ -943,16 +995,6 @@
         if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
           goto Exit;
 
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "cff_face_init: no Unicode cmap is found, "
-                     "and too many subtables (%d) to add synthesized cmap\n",
-                     nn ));
-          goto Exit;
-        }
-#endif
-
         /* we didn't find a Unicode charmap -- synthesize one */
         cmaprec.face        = cffface;
         cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
@@ -973,15 +1015,6 @@
           cffface->charmap = cffface->charmaps[nn];
 
       Skip_Unicode:
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-        if ( nn > FT_MAX_CHARMAP_CACHEABLE )
-        {
-          FT_ERROR(( "cff_face_init: Unicode cmap is found, "
-                     "but too many preceding subtables (%d) to access\n",
-                     nn - 1 ));
-          goto Exit;
-        }
-#endif
         if ( encoding->count > 0 )
         {
           FT_CMap_Class  clazz;
@@ -1055,22 +1088,23 @@
     CFF_Driver  driver = (CFF_Driver)module;
 
 
-    /* set default property values, cf `ftcffdrv.h' */
+    /* set default property values, cf. `ftcffdrv.h' */
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
-    driver->hinting_engine    = FT_CFF_HINTING_FREETYPE;
+    driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
 #else
-    driver->hinting_engine    = FT_CFF_HINTING_ADOBE;
+    driver->hinting_engine = FT_CFF_HINTING_ADOBE;
 #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;
+    driver->no_stem_darkening = TRUE;
+
+    driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+    driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+    driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+    driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+    driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+    driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+    driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+    driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
 
     return FT_Err_Ok;
   }
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index dfbf9a9..9dc7753 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2008, 2013 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFOBJS_H__
-#define __CFFOBJS_H__
+#ifndef CFFOBJS_H_
+#define CFFOBJS_H_
 
 
 #include <ft2build.h>
@@ -179,7 +179,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFOBJS_H__ */
+#endif /* CFFOBJS_H_ */
 
 
 /* END */
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 91bd532..a4f986b 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (body)                                       */
 /*                                                                         */
-/*  Copyright 1996-2004, 2007-2014 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,6 +23,7 @@
 
 #include "cfferrs.h"
 #include "cffpic.h"
+#include "cffgload.h"
 
 
   /*************************************************************************/
@@ -39,7 +40,9 @@
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
-                   FT_Library  library)
+                   FT_Library  library,
+                   FT_UShort   num_designs,
+                   FT_UShort   num_axes )
   {
     FT_MEM_ZERO( parser, sizeof ( *parser ) );
 
@@ -47,6 +50,8 @@
     parser->object_code = code;
     parser->object      = object;
     parser->library     = library;
+    parser->num_designs = num_designs;
+    parser->num_axes    = num_axes;
   }
 
 
@@ -129,7 +134,7 @@
                   FT_Long*  scaling )
   {
     FT_Byte*  p = start;
-    FT_UInt   nib;
+    FT_Int    nib;
     FT_UInt   phase;
 
     FT_Long   result, number, exponent;
@@ -166,7 +171,7 @@
       }
 
       /* Get the nibble. */
-      nib   = ( p[0] >> phase ) & 0xF;
+      nib   = (FT_Int)( p[0] >> phase ) & 0xF;
       phase = 4 - phase;
 
       if ( nib == 0xE )
@@ -188,7 +193,7 @@
     }
 
     /* Read fraction part, if any. */
-    if ( nib == 0xa )
+    if ( nib == 0xA )
       for (;;)
       {
         /* If we entered this iteration with phase == 4, we need */
@@ -516,7 +521,11 @@
 
     if ( parser->top >= parser->stack + 6 )
     {
-      FT_Long  scaling;
+      FT_Fixed  values[6];
+      FT_Long   scalings[6];
+
+      FT_Long  min_scaling, max_scaling;
+      int      i;
 
 
       error = FT_Err_Ok;
@@ -525,22 +534,36 @@
 
       /* We expect a well-formed font matrix, this is, the matrix elements */
       /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
-      /* loss of precision, we use the magnitude of element `xx' to scale  */
-      /* all other elements.  The scaling factor is then contained in the  */
-      /* `units_per_em' value.                                             */
+      /* loss of precision, we use the magnitude of the largest matrix     */
+      /* element to scale all other elements.  The scaling factor is then  */
+      /* contained in the `units_per_em' value.                            */
 
-      matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
+      max_scaling = FT_LONG_MIN;
+      min_scaling = FT_LONG_MAX;
 
-      scaling = -scaling;
+      for ( i = 0; i < 6; i++ )
+      {
+        values[i] = cff_parse_fixed_dynamic( data++, &scalings[i] );
+        if ( values[i] )
+        {
+          if ( scalings[i] > max_scaling )
+            max_scaling = scalings[i];
+          if ( scalings[i] < min_scaling )
+            min_scaling = scalings[i];
+        }
+      }
 
-      if ( scaling < 0 || scaling > 9 )
+      if ( max_scaling < -9                  ||
+           max_scaling > 0                   ||
+           ( max_scaling - min_scaling ) < 0 ||
+           ( max_scaling - min_scaling ) > 9 )
       {
         /* Return default matrix in case of unlikely values. */
 
         FT_TRACE1(( "cff_parse_font_matrix:"
-                    " strange scaling value for xx element (%d),\n"
+                    " strange scaling values (minimum %d, maximum %d),\n"
                     "                      "
-                    " using default matrix\n", scaling ));
+                    " using default matrix\n", min_scaling, max_scaling ));
 
         matrix->xx = 0x10000L;
         matrix->yx = 0;
@@ -553,13 +576,42 @@
         goto Exit;
       }
 
-      matrix->yx = cff_parse_fixed_scaled( data++, scaling );
-      matrix->xy = cff_parse_fixed_scaled( data++, scaling );
-      matrix->yy = cff_parse_fixed_scaled( data++, scaling );
-      offset->x  = cff_parse_fixed_scaled( data++, scaling );
-      offset->y  = cff_parse_fixed_scaled( data,   scaling );
+      for ( i = 0; i < 6; i++ )
+      {
+        FT_Fixed  value = values[i];
+        FT_Long   divisor, half_divisor;
 
-      *upm = power_tens[scaling];
+
+        if ( !value )
+          continue;
+
+        divisor      = power_tens[max_scaling - scalings[i]];
+        half_divisor = divisor >> 1;
+
+        if ( value < 0 )
+        {
+          if ( FT_LONG_MIN + half_divisor < value )
+            values[i] = ( value - half_divisor ) / divisor;
+          else
+            values[i] = FT_LONG_MIN / divisor;
+        }
+        else
+        {
+          if ( FT_LONG_MAX - half_divisor > value )
+            values[i] = ( value + half_divisor ) / divisor;
+          else
+            values[i] = FT_LONG_MAX / divisor;
+        }
+      }
+
+      matrix->xx = values[0];
+      matrix->yx = values[1];
+      matrix->xy = values[2];
+      matrix->yy = values[3];
+      offset->x  = values[4];
+      offset->y  = values[5];
+
+      *upm = (FT_ULong)power_tens[-max_scaling];
 
       FT_TRACE4(( " [%f %f %f %f %f %f]\n",
                   (double)matrix->xx / *upm / 65536,
@@ -617,14 +669,84 @@
 
     if ( parser->top >= parser->stack + 2 )
     {
-      dict->private_size   = cff_parse_num( data++ );
-      dict->private_offset = cff_parse_num( data   );
+      FT_Long  tmp;
+
+
+      tmp = cff_parse_num( data++ );
+      if ( tmp < 0 )
+      {
+        FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Fail;
+      }
+      dict->private_size = (FT_ULong)tmp;
+
+      tmp = cff_parse_num( data );
+      if ( tmp < 0 )
+      {
+        FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Fail;
+      }
+      dict->private_offset = (FT_ULong)tmp;
+
       FT_TRACE4(( " %lu %lu\n",
                   dict->private_size, dict->private_offset ));
 
       error = FT_Err_Ok;
     }
 
+  Fail:
+    return error;
+  }
+
+
+  /* The `MultipleMaster' operator comes before any  */
+  /* top DICT operators that contain T2 charstrings. */
+
+  static FT_Error
+  cff_parse_multiple_master( CFF_Parser  parser )
+  {
+    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
+    FT_Error         error;
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    /* beautify tracing message */
+    if ( ft_trace_levels[FT_COMPONENT] < 4 )
+      FT_TRACE1(( "Multiple Master CFFs not supported yet,"
+                  " handling first master design only\n" ));
+    else
+      FT_TRACE1(( " (not supported yet,"
+                  " handling first master design only)\n" ));
+#endif
+
+    error = FT_ERR( Stack_Underflow );
+
+    /* currently, we handle only the first argument */
+    if ( parser->top >= parser->stack + 5 )
+    {
+      FT_Long  num_designs = cff_parse_num( parser->stack );
+
+
+      if ( num_designs > 16 || num_designs < 2 )
+      {
+        FT_ERROR(( "cff_parse_multiple_master:"
+                   " Invalid number of designs\n" ));
+        error = FT_THROW( Invalid_File_Format );
+      }
+      else
+      {
+        dict->num_designs   = (FT_UShort)num_designs;
+        dict->num_axes      = (FT_UShort)( parser->top - parser->stack - 4 );
+
+        parser->num_designs = dict->num_designs;
+        parser->num_axes    = dict->num_axes;
+
+        error = FT_Err_Ok;
+      }
+    }
+
     return error;
   }
 
@@ -952,7 +1074,7 @@
         if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
           goto Stack_Overflow;
 
-        *parser->top ++ = p;
+        *parser->top++ = p;
 
         /* now, skip it */
         if ( v == 30 )
@@ -981,6 +1103,136 @@
         else if ( v > 246 )
           p += 1;
       }
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+      else if ( v == 31 )
+      {
+        /* a Type 2 charstring */
+
+        CFF_Decoder  decoder;
+        CFF_FontRec  cff_rec;
+        FT_Byte*     charstring_base;
+        FT_ULong     charstring_len;
+
+        FT_Fixed*  stack;
+        FT_Byte*   q;
+
+
+        charstring_base = ++p;
+
+        /* search `endchar' operator */
+        for (;;)
+        {
+          if ( p >= limit )
+            goto Exit;
+          if ( *p == 14 )
+            break;
+          p++;
+        }
+
+        charstring_len = (FT_ULong)( p - charstring_base ) + 1;
+
+        /* construct CFF_Decoder object */
+        FT_MEM_ZERO( &decoder, sizeof ( decoder ) );
+        FT_MEM_ZERO( &cff_rec, sizeof ( cff_rec ) );
+
+        cff_rec.top_font.font_dict.num_designs = parser->num_designs;
+        cff_rec.top_font.font_dict.num_axes    = parser->num_axes;
+        decoder.cff                            = &cff_rec;
+
+        error = cff_decoder_parse_charstrings( &decoder,
+                                               charstring_base,
+                                               charstring_len,
+                                               1 );
+
+        /* Now copy the stack data in the temporary decoder object,    */
+        /* converting it back to charstring number representations     */
+        /* (this is ugly, I know).                                     */
+        /*                                                             */
+        /* We overwrite the original top DICT charstring under the     */
+        /* assumption that the charstring representation of the result */
+        /* of `cff_decoder_parse_charstrings' is shorter, which should */
+        /* be always true.                                             */
+
+        q     = charstring_base - 1;
+        stack = decoder.stack;
+
+        while ( stack < decoder.top )
+        {
+          FT_ULong  num;
+          FT_Bool   neg;
+
+
+          if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+            goto Stack_Overflow;
+
+          *parser->top++ = q;
+
+          if ( *stack < 0 )
+          {
+            num = (FT_ULong)-*stack;
+            neg = 1;
+          }
+          else
+          {
+            num = (FT_ULong)*stack;
+            neg = 0;
+          }
+
+          if ( num & 0xFFFFU )
+          {
+            if ( neg )
+              num = (FT_ULong)-num;
+
+            *q++ = 255;
+            *q++ = ( num & 0xFF000000U ) >> 24;
+            *q++ = ( num & 0x00FF0000U ) >> 16;
+            *q++ = ( num & 0x0000FF00U ) >>  8;
+            *q++ =   num & 0x000000FFU;
+          }
+          else
+          {
+            num >>= 16;
+
+            if ( neg )
+            {
+              if ( num <= 107 )
+                *q++ = (FT_Byte)( 139 - num );
+              else if ( num <= 1131 )
+              {
+                *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 );
+                *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+              }
+              else
+              {
+                num = (FT_ULong)-num;
+
+                *q++ = 28;
+                *q++ = (FT_Byte)( num >> 8 );
+                *q++ = (FT_Byte)( num & 0xFF );
+              }
+            }
+            else
+            {
+              if ( num <= 107 )
+                *q++ = (FT_Byte)( num + 139 );
+              else if ( num <= 1131 )
+              {
+                *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 );
+                *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+              }
+              else
+              {
+                *q++ = 28;
+                *q++ = (FT_Byte)( num >> 8 );
+                *q++ = (FT_Byte)( num & 0xFF );
+              }
+            }
+          }
+
+          stack++;
+        }
+      }
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
       else
       {
         /* This is not a number, hence it's an operator.  Compute its code */
diff --git a/src/cff/cffparse.h b/src/cff/cffparse.h
index 61d91ed..a95970e 100644
--- a/src/cff/cffparse.h
+++ b/src/cff/cffparse.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (specification)                              */
 /*                                                                         */
-/*  Copyright 1996-2003, 2011 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFF_PARSE_H__
-#define __CFF_PARSE_H__
+#ifndef CFFPARSE_H_
+#define CFFPARSE_H_
 
 
 #include <ft2build.h>
@@ -36,16 +36,19 @@
 
   typedef struct  CFF_ParserRec_
   {
-    FT_Library library;
-    FT_Byte*   start;
-    FT_Byte*   limit;
-    FT_Byte*   cursor;
+    FT_Library  library;
+    FT_Byte*    start;
+    FT_Byte*    limit;
+    FT_Byte*    cursor;
 
-    FT_Byte*   stack[CFF_MAX_STACK_DEPTH + 1];
-    FT_Byte**  top;
+    FT_Byte*    stack[CFF_MAX_STACK_DEPTH + 1];
+    FT_Byte**   top;
 
-    FT_UInt    object_code;
-    void*      object;
+    FT_UInt     object_code;
+    void*       object;
+
+    FT_UShort   num_designs; /* a copy of `CFF_FontRecDict->num_designs' */
+    FT_UShort   num_axes;    /* a copy of `CFF_FontRecDict->num_axes'    */
 
   } CFF_ParserRec, *CFF_Parser;
 
@@ -54,7 +57,9 @@
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
-                   FT_Library  library);
+                   FT_Library  library,
+                   FT_UShort   num_designs,
+                   FT_UShort   num_axes );
 
   FT_LOCAL( FT_Error )
   cff_parser_run( CFF_Parser  parser,
@@ -100,7 +105,7 @@
 FT_END_HEADER
 
 
-#endif /* __CFF_PARSE_H__ */
+#endif /* CFFPARSE_H_ */
 
 
 /* END */
diff --git a/src/cff/cffpic.c b/src/cff/cffpic.c
index f22e4f0..a0bc34f 100644
--- a/src/cff/cffpic.c
+++ b/src/cff/cffpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for cff module.      */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/cff/cffpic.h b/src/cff/cffpic.h
index 50bab4c..bed6b35 100644
--- a/src/cff/cffpic.h
+++ b/src/cff/cffpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for cff module.      */
 /*                                                                         */
-/*  Copyright 2009, 2012, 2013 by                                          */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,12 +16,10 @@
 /***************************************************************************/
 
 
-#ifndef __CFFPIC_H__
-#define __CFFPIC_H__
+#ifndef CFFPIC_H_
+#define CFFPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
 
@@ -49,6 +47,8 @@
 #include FT_SERVICE_PROPERTIES_H
 
 
+FT_BEGIN_HEADER
+
   typedef struct  CffModulePIC_
   {
     FT_ServiceDescRec*        cff_services;
@@ -96,13 +96,13 @@
   FT_Error
   cff_driver_class_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
-FT_END_HEADER
-
-#endif /* __CFFPIC_H__ */
+#endif /* CFFPIC_H_ */
 
 
 /* END */
diff --git a/src/cff/cfftoken.h b/src/cff/cfftoken.h
index bcb4276..22637c7 100644
--- a/src/cff/cfftoken.h
+++ b/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token definitions (specification only).                          */
 /*                                                                         */
-/*  Copyright 1996-2003, 2011 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -38,6 +38,9 @@
   CFF_FIELD_NUM     ( 13,    unique_id,           "UniqueID" )
   CFF_FIELD_CALLBACK( 5,     font_bbox,           "FontBBox" )
   CFF_FIELD_NUM     ( 0x108, stroke_width,        "StrokeWidth" )
+#if 0
+  CFF_FIELD_DELTA   ( 14,    xuid, 16,            "XUID" )
+#endif
   CFF_FIELD_NUM     ( 15,    charset_offset,      "charset" )
   CFF_FIELD_NUM     ( 16,    encoding_offset,     "Encoding" )
   CFF_FIELD_NUM     ( 17,    charstrings_offset,  "CharStrings" )
@@ -48,8 +51,13 @@
 #if 0
   CFF_FIELD_STRING  ( 0x116, base_font_name,      "BaseFontName" )
   CFF_FIELD_DELTA   ( 0x117, base_font_blend, 16, "BaseFontBlend" )
+#endif
+
+  /* the next two operators were removed from the Type2 specification */
+  /* in version 16-March-2000                                         */
   CFF_FIELD_CALLBACK( 0x118, multiple_master,     "MultipleMaster" )
-  CFF_FIELD_CALLBACK( 0x119, blend_axis_types,    "BlendAxisTypes" )
+#if 0
+  CFF_FIELD_CALLBACK( 0x11A, blend_axis_types,    "BlendAxisTypes" )
 #endif
 
   CFF_FIELD_CALLBACK( 0x11E, cid_ros,              "ROS" )
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index 8727446..4426c7e 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
 /*    Basic OpenType/CFF type definitions and interface (specification     */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006-2008, 2010-2011, 2013 by                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __CFFTYPES_H__
-#define __CFFTYPES_H__
+#ifndef CFFTYPES_H_
+#define CFFTYPES_H_
 
 
 #include <ft2build.h>
@@ -145,6 +145,12 @@
     FT_ULong   cid_fd_select_offset;
     FT_UInt    cid_font_name;
 
+    /* the next fields come from the data of the deprecated          */
+    /* `MultipleMaster' operator; they are needed to parse the (also */
+    /* deprecated) `blend' operator in Type 2 charstrings            */
+    FT_UShort  num_designs;
+    FT_UShort  num_axes;
+
   } CFF_FontRecDictRec, *CFF_FontRecDict;
 
 
@@ -250,6 +256,7 @@
     FT_UInt          num_strings;
     FT_Byte**        strings;
     FT_Byte*         string_pool;
+    FT_ULong         string_pool_size;
 
     CFF_SubFontRec   top_font;
     FT_UInt          num_subfonts;
@@ -278,7 +285,7 @@
 
 FT_END_HEADER
 
-#endif /* __CFFTYPES_H__ */
+#endif /* CFFTYPES_H_ */
 
 
 /* END */
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
index 2c60b6c..9cab80e 100644
--- a/src/gzip/ftgzip.c
+++ b/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
 /*  parse compressed PCF fonts, as found with many X11 server              */
 /*  distributions.                                                         */
 /*                                                                         */
-/*  Copyright 2002-2006, 2009-2013 by                                      */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -30,7 +30,7 @@
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  Gzip_Err_
@@ -58,9 +58,8 @@
  /* 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 */
+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutil.c */
 #endif
 
 #include "zlib.h"
@@ -208,8 +207,8 @@
 
     /* 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              ||
+    if ( head[0] != 0x1F              ||
+         head[1] != 0x8B              ||
          head[2] != Z_DEFLATED        ||
         (head[3] & FT_GZIP_RESERVED)  )
     {
@@ -378,7 +377,10 @@
       size = stream->read( stream, stream->pos, zip->input,
                            FT_GZIP_BUFFER_SIZE );
       if ( size == 0 )
+      {
+        zip->limit = zip->cursor;
         return FT_THROW( Invalid_Stream_Operation );
+      }
     }
     else
     {
@@ -387,7 +389,10 @@
         size = FT_GZIP_BUFFER_SIZE;
 
       if ( size == 0 )
+      {
+        zip->limit = zip->cursor;
         return FT_THROW( Invalid_Stream_Operation );
+      }
 
       FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
     }
@@ -434,7 +439,8 @@
       }
       else if ( err != Z_OK )
       {
-        error = FT_THROW( Invalid_Stream_Operation );
+        zip->limit = zip->cursor;
+        error      = FT_THROW( Invalid_Stream_Operation );
         break;
       }
     }
@@ -558,19 +564,22 @@
 
       stream->descriptor.pointer = NULL;
     }
+
+    if ( !stream->read )
+      FT_FREE( stream->base );
   }
 
 
-  static FT_ULong
-  ft_gzip_stream_io( FT_Stream  stream,
-                     FT_ULong   pos,
-                     FT_Byte*   buffer,
-                     FT_ULong   count )
+  static unsigned long
+  ft_gzip_stream_io( FT_Stream       stream,
+                     unsigned long   offset,
+                     unsigned char*  buffer,
+                     unsigned long   count )
   {
     FT_GZipFile  zip = (FT_GZipFile)stream->descriptor.pointer;
 
 
-    return ft_gzip_file_io( zip, pos, buffer, count );
+    return ft_gzip_file_io( zip, offset, buffer, count );
   }
 
 
@@ -585,7 +594,7 @@
     old_pos = stream->pos;
     if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
     {
-      result = FT_Stream_ReadULong( stream, &error );
+      result = FT_Stream_ReadULongLE( stream, &error );
       if ( error )
         result = 0;
 
@@ -603,10 +612,18 @@
                       FT_Stream  source )
   {
     FT_Error     error;
-    FT_Memory    memory = source->memory;
+    FT_Memory    memory;
     FT_GZipFile  zip = NULL;
 
 
+    if ( !stream || !source )
+    {
+      error = FT_THROW( Invalid_Stream_Handle );
+      goto Exit;
+    }
+
+    memory = source->memory;
+
     /*
      *  check the header right now; this prevents allocating un-necessary
      *  objects when we don't need them
@@ -674,11 +691,15 @@
         }
         error = FT_Err_Ok;
       }
+
+      if ( zip_size )
+        stream->size = zip_size;
+      else
+        stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
     }
 
-    stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
     stream->pos   = 0;
-    stream->base  = 0;
+    stream->base  = NULL;
     stream->read  = ft_gzip_stream_io;
     stream->close = ft_gzip_stream_close;
 
@@ -700,6 +721,11 @@
     int       err;
 
 
+    /* check for `input' delayed to `inflate' */
+
+    if ( !memory || ! output_len || !output )
+      return FT_THROW( Invalid_Argument );
+
     /* this function is modeled after zlib's `uncompress' function */
 
     stream.next_in  = (Bytef*)input;
diff --git a/src/gzip/inftrees.c b/src/gzip/inftrees.c
index ef53652..56f52b1 100644
--- a/src/gzip/inftrees.c
+++ b/src/gzip/inftrees.c
@@ -115,16 +115,16 @@
   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 */
+  uInt i;                       /* counter, current code */
+  uInt j;                       /* counter */
+  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[] */
+  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) */
+  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 */
diff --git a/src/gzip/zlib.h b/src/gzip/zlib.h
index 50d0d3f..d361ff4 100644
--- a/src/gzip/zlib.h
+++ b/src/gzip/zlib.h
@@ -560,7 +560,7 @@
     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
+  case, the application may save the 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.
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
index 97c130a..ec7311d 100644
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PFR loader (body).                                          */
 /*                                                                         */
-/*  Copyright 2002-2005, 2007, 2009, 2010, 2013, 2014 by                   */
+/*  Copyright 2002-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -179,7 +179,7 @@
     if ( header->signature  != 0x50465230L ||   /* "PFR0" */
          header->version     > 4           ||
          header->header_size < 58          ||
-         header->signature2 != 0x0d0a      )    /* CR/LF  */
+         header->signature2 != 0x0D0A      )    /* CR/LF  */
     {
       result = 0;
     }
@@ -199,7 +199,7 @@
   FT_LOCAL_DEF( FT_Error )
   pfr_log_font_count( FT_Stream  stream,
                       FT_UInt32  section_offset,
-                      FT_UInt   *acount )
+                      FT_Long   *acount )
   {
     FT_Error  error;
     FT_UInt   count;
@@ -212,7 +212,7 @@
     result = count;
 
   Exit:
-    *acount = result;
+    *acount = (FT_Long)result;
     return error;
   }
 
@@ -449,9 +449,9 @@
                                FT_Byte*     limit,
                                PFR_PhyFont  phy_font )
   {
-    FT_Error    error  = FT_Err_Ok;
-    FT_Memory   memory = phy_font->memory;
-    FT_PtrDist  len    = limit - p;
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = phy_font->memory;
+    FT_UInt    len    = (FT_UInt)( limit - p );
 
 
     if ( phy_font->font_id != NULL )
@@ -535,7 +535,8 @@
     item->pair_count = PFR_NEXT_BYTE( p );
     item->base_adj   = PFR_NEXT_SHORT( p );
     item->flags      = PFR_NEXT_BYTE( p );
-    item->offset     = phy_font->offset + ( p - phy_font->cursor );
+    item->offset     = phy_font->offset +
+                       (FT_Offset)( p - phy_font->cursor );
 
 #ifndef PFR_CONFIG_NO_CHECKS
     item->pair_size = 3;
@@ -864,7 +865,7 @@
 
 
       phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
-      phy_font->chars_offset = offset + ( p - stream->cursor );
+      phy_font->chars_offset = offset + (FT_Offset)( p - stream->cursor );
 
       if ( FT_NEW_ARRAY( phy_font->chars, count ) )
         goto Fail;
@@ -898,7 +899,7 @@
 
         cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
                          ? PFR_NEXT_SHORT( p )
-                         : (FT_Int) phy_font->standard_advance;
+                         : phy_font->standard_advance;
 
 #if 0
         cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c
index 6a40e11..3ad44ec 100644
--- a/src/psaux/afmparse.c
+++ b/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    AFM parser (body).                                                   */
 /*                                                                         */
-/*  Copyright 2006-2010, 2012, 2013 by                                     */
+/*  Copyright 2006-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -75,8 +75,8 @@
 #define AFM_STREAM_KEY_BEGIN( stream )    \
           (char*)( (stream)->cursor - 1 )
 
-#define AFM_STREAM_KEY_LEN( stream, key )       \
-          ( (char*)(stream)->cursor - key - 1 )
+#define AFM_STREAM_KEY_LEN( stream, key )           \
+          (FT_Offset)( (char*)(stream)->cursor - key - 1 )
 
 #define AFM_STATUS_EOC( stream ) \
           ( (stream)->status >= AFM_STREAM_STATUS_EOC )
@@ -369,11 +369,11 @@
   FT_LOCAL_DEF( FT_Int )
   afm_parser_read_vals( AFM_Parser  parser,
                         AFM_Value   vals,
-                        FT_UInt     n )
+                        FT_Int      n )
   {
     AFM_Stream  stream = parser->stream;
     char*       str;
-    FT_UInt     i;
+    FT_Int      i;
 
 
     if ( n > AFM_MAX_ARGUMENTS )
@@ -446,7 +446,7 @@
                        FT_Offset*  len )
   {
     AFM_Stream  stream = parser->stream;
-    char*       key    = 0;  /* make stupid compiler happy */
+    char*       key    = NULL;  /* make stupid compiler happy */
 
 
     if ( line )
@@ -562,7 +562,7 @@
   }
 
 
-  FT_LOCAL_DEF( FT_Error )
+  static FT_Error
   afm_parser_read_int( AFM_Parser  parser,
                        FT_Int*     aint )
   {
@@ -590,11 +590,17 @@
     char*          key;
     FT_Offset      len;
     int            n = -1;
+    FT_Int         tmp;
 
 
-    if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
+    if ( afm_parser_read_int( parser, &tmp ) )
         goto Fail;
 
+    if ( tmp < 0 )
+      goto Fail;
+
+    fi->NumTrackKern = (FT_UInt)tmp;
+
     if ( fi->NumTrackKern )
     {
       FT_Memory  memory = parser->memory;
@@ -615,7 +621,7 @@
       case AFM_TOKEN_TRACKKERN:
         n++;
 
-        if ( n >= fi->NumTrackKern )
+        if ( n >= (int)fi->NumTrackKern )
           goto Fail;
 
         tk = fi->TrackKerns + n;
@@ -639,7 +645,7 @@
       case AFM_TOKEN_ENDTRACKKERN:
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
-        fi->NumTrackKern = n + 1;
+        fi->NumTrackKern = (FT_UInt)( n + 1 );
         return FT_Err_Ok;
 
       case AFM_TOKEN_UNKNOWN:
@@ -688,11 +694,17 @@
     char*         key;
     FT_Offset     len;
     int           n = -1;
+    FT_Int        tmp;
 
 
-    if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
+    if ( afm_parser_read_int( parser, &tmp ) )
       goto Fail;
 
+    if ( tmp < 0 )
+      goto Fail;
+
+    fi->NumKernPair = (FT_UInt)tmp;
+
     if ( fi->NumKernPair )
     {
       FT_Memory  memory = parser->memory;
@@ -720,7 +732,7 @@
 
           n++;
 
-          if ( n >= fi->NumKernPair )
+          if ( n >= (int)fi->NumKernPair )
             goto Fail;
 
           kp = fi->KernPairs + n;
@@ -733,8 +745,9 @@
           if ( r < 3 )
             goto Fail;
 
-          kp->index1 = shared_vals[0].u.i;
-          kp->index2 = shared_vals[1].u.i;
+          /* index values can't be negative */
+          kp->index1 = shared_vals[0].u.u;
+          kp->index2 = shared_vals[1].u.u;
           if ( token == AFM_TOKEN_KPY )
           {
             kp->x = 0;
@@ -752,7 +765,7 @@
       case AFM_TOKEN_ENDKERNPAIRS:
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
-        fi->NumKernPair = n + 1;
+        fi->NumKernPair = (FT_UInt)( n + 1 );
         ft_qsort( fi->KernPairs, fi->NumKernPair,
                   sizeof ( AFM_KernPairRec ),
                   afm_compare_kern_pairs );
@@ -815,7 +828,7 @@
 
   static FT_Error
   afm_parser_skip_section( AFM_Parser  parser,
-                           FT_UInt     n,
+                           FT_Int      n,
                            AFM_Token   end_section )
   {
     char*      key;
diff --git a/src/psaux/afmparse.h b/src/psaux/afmparse.h
index 35d9604..f922c4e 100644
--- a/src/psaux/afmparse.h
+++ b/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    AFM parser (specification).                                          */
 /*                                                                         */
-/*  Copyright 2006 by                                                      */
+/*  Copyright 2006-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -61,6 +61,7 @@
       char*     s;
       FT_Fixed  f;
       FT_Int    i;
+      FT_UInt   u;
       FT_Bool   b;
 
     } u;
@@ -72,7 +73,7 @@
   FT_LOCAL( FT_Int )
   afm_parser_read_vals( AFM_Parser  parser,
                         AFM_Value   vals,
-                        FT_UInt     n );
+                        FT_Int      n );
 
   /* read the next key from the next line or column */
   FT_LOCAL( char* )
diff --git a/src/psaux/psaux.c b/src/psaux/psaux.c
index a4b9c5c..7f1d9aa 100644
--- a/src/psaux/psaux.c
+++ b/src/psaux/psaux.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType auxiliary PostScript driver component (body only).          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2006 by                                     */
+/*  Copyright 1996-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/psauxerr.h b/src/psaux/psauxerr.h
index d52375f..97712f0 100644
--- a/src/psaux/psauxerr.h
+++ b/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PS auxiliary module error codes (specification only).                */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/psauxmod.c b/src/psaux/psauxmod.c
index 4b1249d..06fcab0 100644
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType auxiliary PostScript module implementation (body).          */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2006 by                               */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/psauxmod.h b/src/psaux/psauxmod.h
index 1217236..ae6a8f9 100644
--- a/src/psaux/psauxmod.h
+++ b/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType auxiliary PostScript module implementation (specification). */
 /*                                                                         */
-/*  Copyright 2000-2001 by                                                 */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
index d0d8861..aca7412 100644
--- a/src/psaux/psconv.c
+++ b/src/psaux/psconv.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Some convenience conversions (body).                                 */
 /*                                                                         */
-/*  Copyright 2006, 2008, 2009, 2012-2013 by                               */
+/*  Copyright 2006-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -124,7 +124,7 @@
       if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
         break;
 
-      c = ft_char_table[*p & 0x7f];
+      c = ft_char_table[*p & 0x7F];
 
       if ( c < 0 || c >= base )
         break;
@@ -245,12 +245,13 @@
         if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
           break;
 
-        c = ft_char_table[*p & 0x7f];
+        c = ft_char_table[*p & 0x7F];
 
         if ( c < 0 || c >= 10 )
           break;
 
-        if ( decimal < 0xCCCCCCCL )
+        /* only add digit if we don't overflow */
+        if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
         {
           decimal = decimal * 10 + c;
 
@@ -488,8 +489,8 @@
       if ( c OP 0x80 )
         break;
 
-      c = ft_char_table[c & 0x7F];
-      if ( (unsigned)c >= 16 )
+      c = (FT_UInt)ft_char_table[c & 0x7F];
+      if ( c >= 16 )
         break;
 
       pad = ( pad << 4 ) | c;
@@ -520,7 +521,7 @@
       if ( *p OP 0x80 )
         break;
 
-      c = ft_char_table[*p & 0x7f];
+      c = ft_char_table[*p & 0x7F];
 
       if ( (unsigned)c >= 16 )
         break;
diff --git a/src/psaux/psconv.h b/src/psaux/psconv.h
index d91c762..10f1ff7 100644
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Some convenience conversions (specification).                        */
 /*                                                                         */
-/*  Copyright 2006, 2012 by                                                */
+/*  Copyright 2006-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index b4b7d45..c7cbc67 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auxiliary functions for PostScript fonts (body).                     */
 /*                                                                         */
-/*  Copyright 1996-2014 by                                                 */
+/*  Copyright 1996-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -81,7 +81,7 @@
     table->max_elems = count;
     table->init      = 0xDEADBEEFUL;
     table->num_elems = 0;
-    table->block     = 0;
+    table->block     = NULL;
     table->capacity  = 0;
     table->cursor    = 0;
 
@@ -165,10 +165,10 @@
   /*    reallocation fails.                                                */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  ps_table_add( PS_Table    table,
-                FT_Int      idx,
-                void*       object,
-                FT_PtrDist  length )
+  ps_table_add( PS_Table  table,
+                FT_Int    idx,
+                void*     object,
+                FT_UInt   length )
   {
     if ( idx < 0 || idx >= table->max_elems )
     {
@@ -176,12 +176,6 @@
       return FT_THROW( Invalid_Argument );
     }
 
-    if ( length < 0 )
-    {
-      FT_ERROR(( "ps_table_add: invalid length\n" ));
-      return FT_THROW( Invalid_Argument );
-    }
-
     /* grow the base block if needed */
     if ( table->cursor + length > table->capacity )
     {
@@ -625,8 +619,8 @@
 
 
     token->type  = T1_TOKEN_TYPE_NONE;
-    token->start = 0;
-    token->limit = 0;
+    token->start = NULL;
+    token->limit = NULL;
 
     /* first of all, skip leading whitespace */
     ps_parser_skip_spaces( parser );
@@ -707,7 +701,7 @@
 
     if ( !token->limit )
     {
-      token->start = 0;
+      token->start = NULL;
       token->type  = T1_TOKEN_TYPE_NONE;
     }
 
@@ -932,7 +926,7 @@
                FT_Memory  memory )
   {
     FT_Byte*    cur = *cursor;
-    FT_PtrDist  len = 0;
+    FT_UInt     len = 0;
     FT_Int      count;
     FT_String*  result;
     FT_Error    error;
@@ -972,7 +966,7 @@
       }
     }
 
-    len = cur - *cursor;
+    len = (FT_UInt)( cur - *cursor );
     if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
       return 0;
 
@@ -1230,7 +1224,7 @@
 
           for ( i = 0; i < 4; i++ )
           {
-            result = ps_tofixedarray( &cur, limit, max_objects,
+            result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects,
                                       temp + i * max_objects, 0 );
             if ( result < 0 || (FT_UInt)result < max_objects )
             {
@@ -1321,7 +1315,7 @@
       goto Exit;
     }
     if ( (FT_UInt)num_elements > field->array_max )
-      num_elements = field->array_max;
+      num_elements = (FT_Int)field->array_max;
 
     old_cursor = parser->cursor;
     old_limit  = parser->limit;
@@ -1338,7 +1332,15 @@
     {
       parser->cursor = token->start;
       parser->limit  = token->limit;
-      ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
+
+      error = ps_parser_load_field( parser,
+                                    &fieldrec,
+                                    objects,
+                                    max_objects,
+                                    0 );
+      if ( error )
+        break;
+
       fieldrec.offset += fieldrec.size;
     }
 
@@ -1371,7 +1373,7 @@
   ps_parser_to_bytes( PS_Parser  parser,
                       FT_Byte*   bytes,
                       FT_Offset  max_bytes,
-                      FT_Long*   pnum_bytes,
+                      FT_ULong*  pnum_bytes,
                       FT_Bool    delimiters )
   {
     FT_Error  error = FT_Err_Ok;
@@ -1545,7 +1547,7 @@
       FT_GlyphLoader_Rewind( loader );
 
       builder->hints_globals = size->internal;
-      builder->hints_funcs   = 0;
+      builder->hints_funcs   = NULL;
 
       if ( hinting )
         builder->hints_funcs = glyph->internal->glyph_hints;
diff --git a/src/psaux/psobjs.h b/src/psaux/psobjs.h
index e380c60..bf879c1 100644
--- a/src/psaux/psobjs.h
+++ b/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auxiliary functions for PostScript fonts (specification).            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003 by                                     */
+/*  Copyright 1996-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -52,10 +52,10 @@
                 FT_Memory  memory );
 
   FT_LOCAL( FT_Error )
-  ps_table_add( PS_Table    table,
-                FT_Int      idx,
-                void*       object,
-                FT_PtrDist  length );
+  ps_table_add( PS_Table  table,
+                FT_Int    idx,
+                void*     object,
+                FT_UInt   length );
 
   FT_LOCAL( void )
   ps_table_done( PS_Table  table );
@@ -112,7 +112,7 @@
   ps_parser_to_bytes( PS_Parser  parser,
                       FT_Byte*   bytes,
                       FT_Offset  max_bytes,
-                      FT_Long*   pnum_bytes,
+                      FT_ULong*  pnum_bytes,
                       FT_Bool    delimiters );
 
 
diff --git a/src/psaux/t1cmap.c b/src/psaux/t1cmap.c
index 9e5bd34..2e2d433 100644
--- a/src/psaux/t1cmap.c
+++ b/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Type 1 character map support (body).                                 */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2006, 2007, 2012 by                              */
+/*  Copyright 2002-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -39,7 +39,7 @@
     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
 
 
-    cmap->num_glyphs    = face->type1.num_glyphs;
+    cmap->num_glyphs    = (FT_UInt)face->type1.num_glyphs;
     cmap->glyph_names   = (const char* const*)face->type1.glyph_names;
     cmap->sid_to_string = psnames->adobe_std_strings;
     cmap->code_to_sid   = is_expert ? psnames->adobe_expert_encoding
@@ -120,8 +120,12 @@
 
 
   FT_CALLBACK_DEF( FT_Error )
-  t1_cmap_standard_init( T1_CMapStd  cmap )
+  t1_cmap_standard_init( T1_CMapStd  cmap,
+                         FT_Pointer  pointer )
   {
+    FT_UNUSED( pointer );
+
+
     t1_cmap_std_init( cmap, 0 );
     return 0;
   }
@@ -142,8 +146,12 @@
 
 
   FT_CALLBACK_DEF( FT_Error )
-  t1_cmap_expert_init( T1_CMapStd  cmap )
+  t1_cmap_expert_init( T1_CMapStd  cmap,
+                       FT_Pointer  pointer )
   {
+    FT_UNUSED( pointer );
+
+
     t1_cmap_std_init( cmap, 1 );
     return 0;
   }
@@ -172,14 +180,17 @@
 
 
   FT_CALLBACK_DEF( FT_Error )
-  t1_cmap_custom_init( T1_CMapCustom  cmap )
+  t1_cmap_custom_init( T1_CMapCustom  cmap,
+                       FT_Pointer     pointer )
   {
     T1_Face      face     = (T1_Face)FT_CMAP_FACE( cmap );
     T1_Encoding  encoding = &face->type1.encoding;
 
+    FT_UNUSED( pointer );
 
-    cmap->first   = encoding->code_first;
-    cmap->count   = (FT_UInt)( encoding->code_last - cmap->first );
+
+    cmap->first   = (FT_UInt)encoding->code_first;
+    cmap->count   = (FT_UInt)encoding->code_last - cmap->first;
     cmap->indices = encoding->char_index;
 
     FT_ASSERT( cmap->indices != NULL );
@@ -272,16 +283,19 @@
 
 
   FT_CALLBACK_DEF( FT_Error )
-  t1_cmap_unicode_init( PS_Unicodes  unicodes )
+  t1_cmap_unicode_init( PS_Unicodes  unicodes,
+                        FT_Pointer   pointer )
   {
     T1_Face             face    = (T1_Face)FT_CMAP_FACE( unicodes );
     FT_Memory           memory  = FT_FACE_MEMORY( face );
     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
 
+    FT_UNUSED( pointer );
+
 
     return psnames->unicodes_init( memory,
                                    unicodes,
-                                   face->type1.num_glyphs,
+                                   (FT_UInt)face->type1.num_glyphs,
                                    (PS_GetGlyphNameFunc)&psaux_get_glyph_name,
                                    (PS_FreeGlyphNameFunc)NULL,
                                    (FT_Pointer)face );
diff --git a/src/psaux/t1cmap.h b/src/psaux/t1cmap.h
index 7ae65d2..b8ba06c 100644
--- a/src/psaux/t1cmap.h
+++ b/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Type 1 character map support (specification).                        */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2006 by                                          */
+/*  Copyright 2002-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 6ce370b..2e19928 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript Type 1 decoding routines (body).                          */
 /*                                                                         */
-/*  Copyright 2000-2013 by                                                 */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -150,7 +150,7 @@
       if ( name                               &&
            name[0] == glyph_name[0]           &&
            ft_strcmp( name, glyph_name ) == 0 )
-        return n;
+        return (FT_Int)n;
     }
 
     return -1;
@@ -298,7 +298,7 @@
 
     /* the seac operator must not be nested */
     decoder->seac = TRUE;
-    error = t1_decoder_parse_glyph( decoder, bchar_index );
+    error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
     decoder->seac = FALSE;
     if ( error )
       goto Exit;
@@ -320,7 +320,7 @@
 
     /* the seac operator must not be nested */
     decoder->seac = TRUE;
-    error = t1_decoder_parse_glyph( decoder, achar_index );
+    error = t1_decoder_parse_glyph( decoder, (FT_UInt)achar_index );
     decoder->seac = FALSE;
     if ( error )
       goto Exit;
@@ -381,10 +381,10 @@
 
 
     /* compute random seed from stack address of parameter */
-    seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
-                         (FT_PtrDist)(char*)&decoder           ^
-                         (FT_PtrDist)(char*)&charstring_base ) &
-                         FT_ULONG_MAX ) ;
+    seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed            ^
+                         (FT_Offset)(char*)&decoder         ^
+                         (FT_Offset)(char*)&charstring_base ) &
+                         FT_ULONG_MAX                         );
     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
     if ( seed == 0 )
       seed = 0x7384;
@@ -796,7 +796,8 @@
           known_othersubr_result_cnt = 1;
 
           if ( hinter )
-            hinter->reset( hinter->hints, builder->current->n_points );
+            hinter->reset( hinter->hints,
+                           (FT_UInt)builder->current->n_points );
           break;
 
         case 12:
@@ -861,7 +862,7 @@
               *values++ = tmp;
             }
 
-            known_othersubr_result_cnt = num_points;
+            known_othersubr_result_cnt = (FT_Int)num_points;
             break;
           }
 
@@ -879,8 +880,8 @@
 
             idx = Fix2Int( top[0] );
 
-            if ( idx < 0                                           ||
-                 idx + blend->num_designs > decoder->len_buildchar )
+            if ( idx < 0                                                    ||
+                 (FT_UInt)idx + blend->num_designs > decoder->len_buildchar )
               goto Unexpected_OtherSubr;
 
             ft_memcpy( &decoder->buildchar[idx],
@@ -1094,14 +1095,17 @@
           /* close hints recording session */
           if ( hinter )
           {
-            if ( hinter->close( hinter->hints, builder->current->n_points ) )
+            if ( hinter->close( hinter->hints,
+                                (FT_UInt)builder->current->n_points ) )
               goto Syntax_Error;
 
             /* apply hints to the loaded glyph outline now */
-            hinter->apply( hinter->hints,
-                           builder->current,
-                           (PSH_Globals)builder->hints_globals,
-                           decoder->hint_mode );
+            error = hinter->apply( hinter->hints,
+                                   builder->current,
+                                   (PSH_Globals)builder->hints_globals,
+                                   decoder->hint_mode );
+            if ( error )
+              goto Fail;
           }
 
           /* add current outline to the glyph slot */
@@ -1344,7 +1348,7 @@
             FT_TRACE4(( " callsubr" ));
 
             idx = Fix2Int( top[0] );
-            if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
+            if ( idx < 0 || idx >= decoder->num_subrs )
             {
               FT_ERROR(( "t1_decoder_parse_charstrings:"
                          " invalid subrs index\n" ));
@@ -1577,7 +1581,7 @@
 
     /* retrieve PSNames interface from list of current modules */
     {
-      FT_Service_PsCMaps  psnames = 0;
+      FT_Service_PsCMaps  psnames;
 
 
       FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
diff --git a/src/psaux/t1decode.h b/src/psaux/t1decode.h
index 00728db..e83078f 100644
--- a/src/psaux/t1decode.h
+++ b/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript Type 1 decoding routines (specification).                 */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003 by                                     */
+/*  Copyright 2000-2015 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index 644c76d..8f131be 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (body).                                 */
 /*                                                                         */
-/*  Copyright 2001-2010, 2012-2014 by                                      */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -30,16 +30,14 @@
 
 
 #ifdef DEBUG_HINTER
-  PSH_Hint_Table  ps_debug_hint_table = 0;
-  PSH_HintFunc    ps_debug_hint_func  = 0;
-  PSH_Glyph       ps_debug_glyph      = 0;
+  PSH_Hint_Table  ps_debug_hint_table = NULL;
+  PSH_HintFunc    ps_debug_hint_func  = NULL;
+  PSH_Glyph       ps_debug_glyph      = NULL;
 #endif
 
 
 #define  COMPUTE_INFLEXS  /* compute inflection points to optimize `S' */
                           /* and similar glyphs                        */
-#define  STRONGER         /* slightly increase the contrast of smooth  */
-                          /* hinting                                   */
 
 
   /*************************************************************************/
@@ -67,13 +65,13 @@
   {
     FT_FREE( table->zones );
     table->num_zones = 0;
-    table->zone      = 0;
+    table->zone      = NULL;
 
     FT_FREE( table->sort );
     FT_FREE( table->hints );
     table->num_hints   = 0;
     table->max_hints   = 0;
-    table->sort_global = 0;
+    table->sort_global = NULL;
   }
 
 
@@ -121,7 +119,7 @@
       PSH_Hint   hint2;
 
 
-      hint->parent = 0;
+      hint->parent = NULL;
       for ( ; count > 0; count--, sorted++ )
       {
         hint2 = sorted[0];
@@ -194,7 +192,7 @@
     table->sort_global = table->sort + count;
     table->num_hints   = 0;
     table->num_zones   = 0;
-    table->zone        = 0;
+    table->zone        = NULL;
 
     /* initialize the `table->hints' array */
     {
@@ -781,7 +779,7 @@
            * It turns out though that minimizing the total number of lit
            * pixels is also important, so position C), with one edge
            * aligned with a pixel boundary is actually preferable
-           * to A).  There are also more possibile positions for C) than
+           * to A).  There are also more possible positions for C) than
            * for A) or B), so it involves less distortion of the overall
            * character shape.
            */
@@ -804,7 +802,7 @@
             }
 
             /* We choose between B) and C) above based on the amount
-             * of fractinal stem width; for small amounts, choose
+             * of fractional stem width; for small amounts, choose
              * C) always, for large amounts, B) always, and inbetween,
              * pick whichever one involves less stem movement.
              */
@@ -890,9 +888,6 @@
   /*************************************************************************/
   /*************************************************************************/
 
-#define PSH_ZONE_MIN  -3200000L
-#define PSH_ZONE_MAX  +3200000L
-
 #define xxDEBUG_ZONES
 
 
@@ -910,10 +905,6 @@
              zone->max );
   }
 
-#else
-
-#define psh_print_zone( x )  do { } while ( 0 )
-
 #endif /* DEBUG_ZONES */
 
 
@@ -925,103 +916,9 @@
   /*************************************************************************/
   /*************************************************************************/
 
-#if 1
-
 #define  psh_corner_is_flat      ft_corner_is_flat
 #define  psh_corner_orientation  ft_corner_orientation
 
-#else
-
-  FT_LOCAL_DEF( FT_Int )
-  psh_corner_is_flat( FT_Pos  x_in,
-                      FT_Pos  y_in,
-                      FT_Pos  x_out,
-                      FT_Pos  y_out )
-  {
-    FT_Pos  ax = x_in;
-    FT_Pos  ay = y_in;
-
-    FT_Pos  d_in, d_out, d_corner;
-
-
-    if ( ax < 0 )
-      ax = -ax;
-    if ( ay < 0 )
-      ay = -ay;
-    d_in = ax + ay;
-
-    ax = x_out;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = y_out;
-    if ( ay < 0 )
-      ay = -ay;
-    d_out = ax + ay;
-
-    ax = x_out + x_in;
-    if ( ax < 0 )
-      ax = -ax;
-    ay = y_out + y_in;
-    if ( ay < 0 )
-      ay = -ay;
-    d_corner = ax + ay;
-
-    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
-  }
-
-  static FT_Int
-  psh_corner_orientation( FT_Pos  in_x,
-                          FT_Pos  in_y,
-                          FT_Pos  out_x,
-                          FT_Pos  out_y )
-  {
-    FT_Int  result;
-
-
-    /* deal with the trivial cases quickly */
-    if ( in_y == 0 )
-    {
-      if ( in_x >= 0 )
-        result = out_y;
-      else
-        result = -out_y;
-    }
-    else if ( in_x == 0 )
-    {
-      if ( in_y >= 0 )
-        result = -out_x;
-      else
-        result = out_x;
-    }
-    else if ( out_y == 0 )
-    {
-      if ( out_x >= 0 )
-        result = in_y;
-      else
-        result = -in_y;
-    }
-    else if ( out_x == 0 )
-    {
-      if ( out_y >= 0 )
-        result = -in_x;
-      else
-        result =  in_x;
-    }
-    else /* general case */
-    {
-      long long  delta = (long long)in_x * out_y - (long long)in_y * out_x;
-
-      if ( delta == 0 )
-        result = 0;
-      else
-        result = 1 - 2 * ( delta < 0 );
-    }
-
-    return result;
-  }
-
-#endif /* !1 */
-
 
 #ifdef COMPUTE_INFLEXS
 
@@ -1149,7 +1046,7 @@
     glyph->num_points   = 0;
     glyph->num_contours = 0;
 
-    glyph->memory = 0;
+    glyph->memory = NULL;
   }
 
 
@@ -1274,8 +1171,8 @@
          FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
       goto Exit;
 
-    glyph->num_points   = outline->n_points;
-    glyph->num_contours = outline->n_contours;
+    glyph->num_points   = (FT_UInt)outline->n_points;
+    glyph->num_contours = (FT_UInt)outline->n_contours;
 
     {
       FT_UInt      first = 0, next, n;
@@ -1285,15 +1182,15 @@
 
       for ( n = 0; n < glyph->num_contours; n++ )
       {
-        FT_Int     count;
+        FT_UInt    count;
         PSH_Point  point;
 
 
-        next  = outline->contours[n] + 1;
+        next  = (FT_UInt)outline->contours[n] + 1;
         count = next - first;
 
         contour->start = points + first;
-        contour->count = (FT_UInt)count;
+        contour->count = count;
 
         if ( count > 0 )
         {
@@ -1696,16 +1593,12 @@
       mask++;
       for ( ; num_masks > 1; num_masks--, mask++ )
       {
-        FT_UInt  next;
-        FT_Int   count;
+        FT_UInt  next = FT_MIN( mask->end_point, glyph->num_points );
 
 
-        next  = mask->end_point > glyph->num_points
-                  ? glyph->num_points
-                  : mask->end_point;
-        count = next - first;
-        if ( count > 0 )
+        if ( next > first )
         {
+          FT_UInt    count = next - first;
           PSH_Point  point = glyph->points + first;
 
 
@@ -2048,7 +1941,7 @@
       /* count the number of strong points in this contour */
       next      = start + contour->count;
       fit_count = 0;
-      first     = 0;
+      first     = NULL;
 
       for ( point = start; point < next; point++ )
         if ( psh_point_is_fitted( point ) )
diff --git a/src/pshinter/pshalgo.h b/src/pshinter/pshalgo.h
index c70f31e..f1bda65 100644
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (specification).                        */
 /*                                                                         */
-/*  Copyright 2001-2003, 2008, 2013 by                                     */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __PSHALGO_H__
-#define __PSHALGO_H__
+#ifndef PSHALGO_H_
+#define PSHALGO_H_
 
 
 #include "pshrec.h"
@@ -30,15 +30,12 @@
   /* handle to Hint structure */
   typedef struct PSH_HintRec_*  PSH_Hint;
 
-  /* hint bit-flags */
-  typedef enum  PSH_Hint_Flags_
-  {
-    PSH_HINT_GHOST  = PS_HINT_FLAG_GHOST,
-    PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
-    PSH_HINT_ACTIVE = 4,
-    PSH_HINT_FITTED = 8
 
-  } PSH_Hint_Flags;
+  /* hint bit-flags */
+#define PSH_HINT_GHOST   PS_HINT_FLAG_GHOST
+#define PSH_HINT_BOTTOM  PS_HINT_FLAG_BOTTOM
+#define PSH_HINT_ACTIVE  4U
+#define PSH_HINT_FITTED  8U
 
 
 #define psh_hint_is_active( x )  ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )
@@ -49,6 +46,7 @@
 #define psh_hint_deactivate( x )  (x)->flags &= ~PSH_HINT_ACTIVE
 #define psh_hint_set_fitted( x )  (x)->flags |=  PSH_HINT_FITTED
 
+
   /* hint structure */
   typedef struct  PSH_HintRec_
   {
@@ -112,14 +110,12 @@
 #define PSH_DIR_IS_VERTICAL( d )    PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
 
 
- /* the following bit-flags are computed once by the glyph */
- /* analyzer, for both dimensions                          */
-  enum
-  {
-    PSH_POINT_OFF    = 1,   /* point is off the curve */
-    PSH_POINT_SMOOTH = 2,   /* point is smooth        */
-    PSH_POINT_INFLEX = 4    /* point is inflection    */
-  };
+  /* the following bit-flags are computed once by the glyph */
+  /* analyzer, for both dimensions                          */
+#define PSH_POINT_OFF     1U      /* point is off the curve */
+#define PSH_POINT_SMOOTH  2U      /* point is smooth        */
+#define PSH_POINT_INFLEX  4U      /* point is inflection    */
+
 
 #define psh_point_is_smooth( p )  ( (p)->flags & PSH_POINT_SMOOTH )
 #define psh_point_is_off( p )     ( (p)->flags & PSH_POINT_OFF    )
@@ -129,17 +125,16 @@
 #define psh_point_set_off( p )     (p)->flags |= PSH_POINT_OFF
 #define psh_point_set_inflex( p )  (p)->flags |= PSH_POINT_INFLEX
 
+
   /* the following bit-flags are re-computed for each dimension */
-  enum
-  {
-    PSH_POINT_STRONG   = 16,   /* point is strong                           */
-    PSH_POINT_FITTED   = 32,   /* point is already fitted                   */
-    PSH_POINT_EXTREMUM = 64,   /* point is local extremum                   */
-    PSH_POINT_POSITIVE = 128,  /* extremum has positive contour flow        */
-    PSH_POINT_NEGATIVE = 256,  /* extremum has negative contour flow        */
-    PSH_POINT_EDGE_MIN = 512,  /* point is aligned to left/bottom stem edge */
-    PSH_POINT_EDGE_MAX = 1024  /* point is aligned to top/right stem edge   */
-  };
+#define PSH_POINT_STRONG      16U /* point is strong                           */
+#define PSH_POINT_FITTED      32U /* point is already fitted                   */
+#define PSH_POINT_EXTREMUM    64U /* point is local extremum                   */
+#define PSH_POINT_POSITIVE   128U /* extremum has positive contour flow        */
+#define PSH_POINT_NEGATIVE   256U /* extremum has negative contour flow        */
+#define PSH_POINT_EDGE_MIN   512U /* point is aligned to left/bottom stem edge */
+#define PSH_POINT_EDGE_MAX  1024U /* point is aligned to top/right stem edge   */
+
 
 #define psh_point_is_strong( p )    ( (p)->flags2 & PSH_POINT_STRONG )
 #define psh_point_is_fitted( p )    ( (p)->flags2 & PSH_POINT_FITTED )
@@ -240,7 +235,7 @@
 FT_END_HEADER
 
 
-#endif /* __PSHALGO_H__ */
+#endif /* PSHALGO_H_ */
 
 
 /* END */
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index f75bae4..2ac5ef1 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, 2013 by                         */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -23,7 +23,7 @@
 #include "pshglob.h"
 
 #ifdef DEBUG_HINTER
-  PSH_Globals  ps_debug_globals = 0;
+  PSH_Globals  ps_debug_globals = NULL;
 #endif
 
 
@@ -80,7 +80,7 @@
 
 #if 0
 
-  /* org_width is is font units, result in device pixels, 26.6 format */
+  /* org_width is in font units, result in device pixels, 26.6 format */
   FT_LOCAL_DEF( FT_Pos )
   psh_dimension_snap_width( PSH_Dimension  dimension,
                             FT_Int         org_width )
@@ -240,7 +240,7 @@
                        FT_Int     family )
   {
     PSH_Blue_Table  top_table, bot_table;
-    FT_Int          count_top, count_bot;
+    FT_UInt         count_top, count_bot;
 
 
     if ( family )
@@ -339,7 +339,7 @@
             bot   = zone[1].org_bottom;
             delta = bot - top;
 
-            if ( delta < 2 * fuzz )
+            if ( delta / 2 < fuzz )
               zone[0].org_top = zone[1].org_bottom = top + delta / 2;
             else
             {
@@ -369,7 +369,7 @@
   {
     FT_UInt         count;
     FT_UInt         num;
-    PSH_Blue_Table  table = 0;
+    PSH_Blue_Table  table = NULL;
 
     /*                                                        */
     /* Determine whether we need to suppress overshoots or    */
@@ -635,7 +635,7 @@
       FT_FREE( globals );
 
 #ifdef DEBUG_HINTER
-      ps_debug_globals = 0;
+      ps_debug_globals = NULL;
 #endif
     }
   }
@@ -750,7 +750,7 @@
   }
 
 
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   psh_globals_set_scale( PSH_Globals  globals,
                          FT_Fixed     x_scale,
                          FT_Fixed     y_scale,
@@ -780,8 +780,6 @@
       psh_globals_scale_widths( globals, 1 );
       psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
     }
-
-    return 0;
   }
 
 
diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h
index c511626..45c957b 100644
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinter global hinting management.                         */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003 by                                          */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __PSHGLOB_H__
-#define __PSHGLOB_H__
+#ifndef PSHGLOB_H_
+#define PSHGLOB_H_
 
 
 #include FT_FREETYPE_H
@@ -167,7 +167,7 @@
                             FT_Int         org_width );
 #endif
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   psh_globals_set_scale( PSH_Globals  globals,
                          FT_Fixed     x_scale,
                          FT_Fixed     y_scale,
@@ -190,7 +190,7 @@
 FT_END_HEADER
 
 
-#endif /* __PSHGLOB_H__ */
+#endif /* PSHGLOB_H_ */
 
 
 /* END */
diff --git a/src/pshinter/pshinter.c b/src/pshinter/pshinter.c
index b35a2a9..614e0bb 100644
--- a/src/pshinter/pshinter.c
+++ b/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript Hinting module                                   */
 /*                                                                         */
-/*  Copyright 2001, 2003 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/pshinter/pshmod.c b/src/pshinter/pshmod.c
index cdeaca1..fa4ad1f 100644
--- a/src/pshinter/pshmod.c
+++ b/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hinter module implementation (body).             */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2007, 2009, 2012 by                              */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/pshinter/pshmod.h b/src/pshinter/pshmod.h
index 0ae7e96..39112a9 100644
--- a/src/pshinter/pshmod.h
+++ b/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinter module interface (specification).                  */
 /*                                                                         */
-/*  Copyright 2001 by                                                      */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __PSHMOD_H__
-#define __PSHMOD_H__
+#ifndef PSHMOD_H_
+#define PSHMOD_H_
 
 
 #include <ft2build.h>
@@ -33,7 +33,7 @@
 FT_END_HEADER
 
 
-#endif /* __PSHMOD_H__ */
+#endif /* PSHMOD_H_ */
 
 
 /* END */
diff --git a/src/pshinter/pshnterr.h b/src/pshinter/pshnterr.h
index 7cc180f..7a94588 100644
--- a/src/pshinter/pshnterr.h
+++ b/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PS Hinter error codes (specification only).                          */
 /*                                                                         */
-/*  Copyright 2003, 2012 by                                                */
+/*  Copyright 2003-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,12 +22,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __PSHNTERR_H__
-#define __PSHNTERR_H__
+#ifndef PSHNTERR_H_
+#define PSHNTERR_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  PSH_Err_
@@ -35,7 +35,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __PSHNTERR_H__ */
+#endif /* PSHNTERR_H_ */
 
 
 /* END */
diff --git a/src/pshinter/pshpic.c b/src/pshinter/pshpic.c
index 568f4ac..d0a3d8e 100644
--- a/src/pshinter/pshpic.c
+++ b/src/pshinter/pshpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for pshinter module. */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/pshinter/pshpic.h b/src/pshinter/pshpic.h
index b46f853..75ee573 100644
--- a/src/pshinter/pshpic.h
+++ b/src/pshinter/pshpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for pshinter module. */
 /*                                                                         */
-/*  Copyright 2009, 2012, 2013 by                                          */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,12 +16,10 @@
 /***************************************************************************/
 
 
-#ifndef __PSHPIC_H__
-#define __PSHPIC_H__
+#ifndef PSHPIC_H_
+#define PSHPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
 
@@ -33,6 +31,8 @@
 
 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
+FT_BEGIN_HEADER
+
   typedef struct  PSHinterPIC_
   {
     PSHinter_Interface  pshinter_interface;
@@ -51,13 +51,13 @@
   FT_Error
   pshinter_module_class_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
-FT_END_HEADER
-
-#endif /* __PSHPIC_H__ */
+#endif /* PSHPIC_H_ */
 
 
 /* END */
diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c
index cd66ea8..d7cc4a0 100644
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hints recorder (body).                           */
 /*                                                                         */
-/*  Copyright 2001-2004, 2007, 2009, 2013 by                               */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,7 +31,7 @@
 #define FT_COMPONENT  trace_pshrec
 
 #ifdef DEBUG_HINTER
-  PS_Hints  ps_debug_hints         = 0;
+  PS_Hints  ps_debug_hints         = NULL;
   int       ps_debug_no_horz_hints = 0;
   int       ps_debug_no_vert_hints = 0;
 #endif
@@ -85,7 +85,7 @@
   {
     FT_Error  error = FT_Err_Ok;
     FT_UInt   count;
-    PS_Hint   hint = 0;
+    PS_Hint   hint = NULL;
 
 
     count = table->num_hints;
@@ -167,12 +167,12 @@
   /* clear a given bit */
   static void
   ps_mask_clear_bit( PS_Mask  mask,
-                     FT_Int   idx )
+                     FT_UInt  idx )
   {
     FT_Byte*  p;
 
 
-    if ( (FT_UInt)idx >= mask->num_bits )
+    if ( idx >= mask->num_bits )
       return;
 
     p    = mask->bytes + ( idx >> 3 );
@@ -183,17 +183,14 @@
   /* set a given bit, possibly grow the mask */
   static FT_Error
   ps_mask_set_bit( PS_Mask    mask,
-                   FT_Int     idx,
+                   FT_UInt    idx,
                    FT_Memory  memory )
   {
     FT_Error  error = FT_Err_Ok;
     FT_Byte*  p;
 
 
-    if ( idx < 0 )
-      goto Exit;
-
-    if ( (FT_UInt)idx >= mask->num_bits )
+    if ( idx >= mask->num_bits )
     {
       error = ps_mask_ensure( mask, idx + 1, memory );
       if ( error )
@@ -257,7 +254,7 @@
   {
     FT_UInt   count;
     FT_Error  error = FT_Err_Ok;
-    PS_Mask   mask  = 0;
+    PS_Mask   mask  = NULL;
 
 
     count = table->num_masks;
@@ -372,8 +369,8 @@
   /* test whether two masks in a table intersect */
   static FT_Int
   ps_mask_table_test_intersect( PS_Mask_Table  table,
-                                FT_Int         index1,
-                                FT_Int         index2 )
+                                FT_UInt        index1,
+                                FT_UInt        index2 )
   {
     PS_Mask   mask1  = table->masks + index1;
     PS_Mask   mask2  = table->masks + index2;
@@ -404,23 +401,25 @@
   /* merge two masks, used by ps_mask_table_merge_all */
   static FT_Error
   ps_mask_table_merge( PS_Mask_Table  table,
-                       FT_Int         index1,
-                       FT_Int         index2,
+                       FT_UInt        index1,
+                       FT_UInt        index2,
                        FT_Memory      memory )
   {
-    FT_UInt   temp;
     FT_Error  error = FT_Err_Ok;
 
 
     /* swap index1 and index2 so that index1 < index2 */
     if ( index1 > index2 )
     {
+      FT_UInt  temp;
+
+
       temp   = index1;
       index1 = index2;
       index2 = temp;
     }
 
-    if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
+    if ( index1 < index2 && index2 < table->num_masks )
     {
       /* we need to merge the bitsets of index1 and index2 with a */
       /* simple union                                             */
@@ -453,7 +452,7 @@
         /* merge (unite) the bitsets */
         read  = mask2->bytes;
         write = mask1->bytes;
-        pos   = (FT_UInt)( ( count2 + 7 ) >> 3 );
+        pos   = ( count2 + 7 ) >> 3;
 
         for ( ; pos > 0; pos-- )
         {
@@ -468,14 +467,17 @@
       mask2->num_bits  = 0;
       mask2->end_point = 0;
 
-      delta = table->num_masks - 1 - index2; /* number of masks to move */
+      /* number of masks to move */
+      delta = (FT_Int)( table->num_masks - 1 - index2 );
       if ( delta > 0 )
       {
         /* move to end of table for reuse */
         PS_MaskRec  dummy = *mask2;
 
 
-        ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
+        ft_memmove( mask2,
+                    mask2 + 1,
+                    (FT_UInt)delta * sizeof ( PS_MaskRec ) );
 
         mask2[delta] = dummy;
       }
@@ -502,13 +504,19 @@
     FT_Error  error = FT_Err_Ok;
 
 
-    for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
+    /* both loops go down to 0, thus FT_Int for index1 and index2 */
+    for ( index1 = (FT_Int)table->num_masks - 1; index1 > 0; index1-- )
     {
       for ( index2 = index1 - 1; index2 >= 0; index2-- )
       {
-        if ( ps_mask_table_test_intersect( table, index1, index2 ) )
+        if ( ps_mask_table_test_intersect( table,
+                                           (FT_UInt)index1,
+                                           (FT_UInt)index2 ) )
         {
-          error = ps_mask_table_merge( table, index2, index1, memory );
+          error = ps_mask_table_merge( table,
+                                       (FT_UInt)index2,
+                                       (FT_UInt)index1,
+                                       memory );
           if ( error )
             goto Exit;
 
@@ -670,8 +678,8 @@
     {
       PS_Mask  mask;
       FT_UInt  idx;
-      FT_UInt  max   = dim->hints.num_hints;
-      PS_Hint  hint  = dim->hints.hints;
+      FT_UInt  max  = dim->hints.num_hints;
+      PS_Hint  hint = dim->hints.hints;
 
 
       for ( idx = 0; idx < max; idx++, hint++ )
@@ -742,17 +750,26 @@
     }
 
     /* now, set the bits for our hints in the counter mask */
-    error = ps_mask_set_bit( counter, hint1, memory );
-    if ( error )
-      goto Exit;
+    if ( hint1 >= 0 )
+    {
+      error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory );
+      if ( error )
+        goto Exit;
+    }
 
-    error = ps_mask_set_bit( counter, hint2, memory );
-    if ( error )
-      goto Exit;
+    if ( hint2 >= 0 )
+    {
+      error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory );
+      if ( error )
+        goto Exit;
+    }
 
-    error = ps_mask_set_bit( counter, hint3, memory );
-    if ( error )
-      goto Exit;
+    if ( hint3 >= 0 )
+    {
+      error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory );
+      if ( error )
+        goto Exit;
+    }
 
   Exit:
     return error;
@@ -793,17 +810,16 @@
     ps_dimension_done( &hints->dimension[1], memory );
 
     hints->error  = FT_Err_Ok;
-    hints->memory = 0;
+    hints->memory = NULL;
   }
 
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   ps_hints_init( PS_Hints   hints,
                  FT_Memory  memory )
   {
     FT_MEM_ZERO( hints, sizeof ( *hints ) );
     hints->memory = memory;
-    return FT_Err_Ok;
   }
 
 
@@ -812,78 +828,57 @@
   ps_hints_open( PS_Hints      hints,
                  PS_Hint_Type  hint_type )
   {
-    switch ( hint_type )
-    {
-    case PS_HINT_TYPE_1:
-    case PS_HINT_TYPE_2:
-      hints->error     = FT_Err_Ok;
-      hints->hint_type = hint_type;
+    hints->error     = FT_Err_Ok;
+    hints->hint_type = hint_type;
 
-      ps_dimension_init( &hints->dimension[0] );
-      ps_dimension_init( &hints->dimension[1] );
-      break;
-
-    default:
-      hints->error     = FT_THROW( Invalid_Argument );
-      hints->hint_type = hint_type;
-
-      FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));
-      break;
-    }
+    ps_dimension_init( &hints->dimension[0] );
+    ps_dimension_init( &hints->dimension[1] );
   }
 
 
   /* add one or more stems to the current hints table */
   static void
   ps_hints_stem( PS_Hints  hints,
-                 FT_Int    dimension,
-                 FT_UInt   count,
+                 FT_UInt   dimension,
+                 FT_Int    count,
                  FT_Long*  stems )
   {
-    if ( !hints->error )
+    PS_Dimension  dim;
+
+
+    if ( hints->error )
+      return;
+
+    /* limit "dimension" to 0..1 */
+    if ( dimension > 1 )
     {
-      /* limit "dimension" to 0..1 */
-      if ( dimension < 0 || dimension > 1 )
+      FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
+                  dimension ));
+      dimension = ( dimension != 0 );
+    }
+
+    /* record the stems in the current hints/masks table */
+    /* (Type 1 & 2's `hstem' or `vstem' operators)       */
+    dim = &hints->dimension[dimension];
+
+    for ( ; count > 0; count--, stems += 2 )
+    {
+      FT_Error   error;
+      FT_Memory  memory = hints->memory;
+
+
+      error = ps_dimension_add_t1stem( dim,
+                                       (FT_Int)stems[0],
+                                       (FT_Int)stems[1],
+                                       memory,
+                                       NULL );
+      if ( error )
       {
-        FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
-                    dimension ));
-        dimension = ( dimension != 0 );
-      }
+        FT_ERROR(( "ps_hints_stem: could not add stem"
+                   " (%d,%d) to hints table\n", stems[0], stems[1] ));
 
-      /* record the stems in the current hints/masks table */
-      switch ( hints->hint_type )
-      {
-      case PS_HINT_TYPE_1:  /* Type 1 "hstem" or "vstem" operator */
-      case PS_HINT_TYPE_2:  /* Type 2 "hstem" or "vstem" operator */
-        {
-          PS_Dimension  dim = &hints->dimension[dimension];
-
-
-          for ( ; count > 0; count--, stems += 2 )
-          {
-            FT_Error   error;
-            FT_Memory  memory = hints->memory;
-
-
-            error = ps_dimension_add_t1stem(
-                      dim, (FT_Int)stems[0], (FT_Int)stems[1],
-                      memory, NULL );
-            if ( error )
-            {
-              FT_ERROR(( "ps_hints_stem: could not add stem"
-                         " (%d,%d) to hints table\n", stems[0], stems[1] ));
-
-              hints->error = error;
-              return;
-            }
-          }
-          break;
-        }
-
-      default:
-        FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n",
-                    hints->hint_type ));
-        break;
+        hints->error = error;
+        return;
       }
     }
   }
@@ -892,7 +887,7 @@
   /* add one Type1 counter stem to the current hints table */
   static void
   ps_hints_t1stem3( PS_Hints   hints,
-                    FT_Int     dimension,
+                    FT_UInt    dimension,
                     FT_Fixed*  stems )
   {
     FT_Error  error = FT_Err_Ok;
@@ -907,7 +902,7 @@
 
 
       /* limit "dimension" to 0..1 */
-      if ( dimension < 0 || dimension > 1 )
+      if ( dimension > 1 )
       {
         FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
                     dimension ));
@@ -1129,7 +1124,7 @@
 
   static void
   t1_hints_stem( T1_Hints   hints,
-                 FT_Int     dimension,
+                 FT_UInt    dimension,
                  FT_Fixed*  coords )
   {
     FT_Pos  stems[2];
@@ -1173,12 +1168,12 @@
 
   static void
   t2_hints_stems( T2_Hints   hints,
-                  FT_Int     dimension,
+                  FT_UInt    dimension,
                   FT_Int     count,
                   FT_Fixed*  coords )
   {
-    FT_Pos  stems[32], y, n;
-    FT_Int  total = count;
+    FT_Pos  stems[32], y;
+    FT_Int  total = count, n;
 
 
     y = 0;
diff --git a/src/pshinter/pshrec.h b/src/pshinter/pshrec.h
index dcb3197..97e6f0e 100644
--- a/src/pshinter/pshrec.h
+++ b/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Postscript (Type1/Type2) hints recorder (specification).             */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2006, 2008 by                              */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,8 +28,8 @@
   /**************************************************************************/
 
 
-#ifndef __PSHREC_H__
-#define __PSHREC_H__
+#ifndef PSHREC_H_
+#define PSHREC_H_
 
 
 #include <ft2build.h>
@@ -61,12 +61,8 @@
 
 
   /* hint flags */
-  typedef enum  PS_Hint_Flags_
-  {
-    PS_HINT_FLAG_GHOST  = 1,
-    PS_HINT_FLAG_BOTTOM = 2
-
-  } PS_Hint_Flags;
+#define PS_HINT_FLAG_GHOST   1U
+#define PS_HINT_FLAG_BOTTOM  2U
 
 
   /* hint descriptor */
@@ -141,7 +137,7 @@
   /* */
 
   /* initialize hints recorder */
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   ps_hints_init( PS_Hints   hints,
                  FT_Memory  memory );
 
@@ -170,7 +166,7 @@
 FT_END_HEADER
 
 
-#endif /* __PS_HINTER_RECORD_H__ */
+#endif /* PSHREC_H_ */
 
 
 /* END */
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index 0a5bcb7..345402d 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PSNames module implementation (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005-2008, 2012, 2013 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -312,7 +312,7 @@
 
     /* we first allocate the table */
     table->num_maps = 0;
-    table->maps     = 0;
+    table->maps     = NULL;
 
     if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
     {
@@ -525,31 +525,31 @@
 
   FT_DEFINE_SERVICE_PSCMAPSREC(
     pscmaps_interface,
-    (PS_Unicode_ValueFunc)     ps_unicode_value,
-    (PS_Unicodes_InitFunc)     ps_unicodes_init,
-    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
-    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
+    (PS_Unicode_ValueFunc)     ps_unicode_value,        /* unicode_value         */
+    (PS_Unicodes_InitFunc)     ps_unicodes_init,        /* unicodes_init         */
+    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,  /* unicodes_char_index   */
+    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,   /* unicodes_char_next    */
 
-    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
-    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
+    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
 
-    t1_standard_encoding,
-    t1_expert_encoding )
+    t1_standard_encoding,                               /* adobe_std_encoding    */
+    t1_expert_encoding )                                /* adobe_expert_encoding */
 
 #else
 
   FT_DEFINE_SERVICE_PSCMAPSREC(
     pscmaps_interface,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+    NULL,                                               /* unicode_value         */
+    NULL,                                               /* unicodes_init         */
+    NULL,                                               /* unicodes_char_index   */
+    NULL,                                               /* unicodes_char_next    */
 
-    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
-    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
+    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
 
-    t1_standard_encoding,
-    t1_expert_encoding )
+    t1_standard_encoding,                               /* adobe_std_encoding    */
+    t1_expert_encoding )                                /* adobe_expert_encoding */
 
 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
 
@@ -563,7 +563,7 @@
   psnames_get_service( FT_Module    module,
                        const char*  service_id )
   {
-    /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
+    /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     FT_Library  library;
 
diff --git a/src/psnames/psmodule.h b/src/psnames/psmodule.h
index 28fa148..ee3c6cb 100644
--- a/src/psnames/psmodule.h
+++ b/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level PSNames module interface (specification).                 */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __PSMODULE_H__
-#define __PSMODULE_H__
+#ifndef PSMODULE_H_
+#define PSMODULE_H_
 
 
 #include <ft2build.h>
@@ -32,7 +32,7 @@
 
 FT_END_HEADER
 
-#endif /* __PSMODULE_H__ */
+#endif /* PSMODULE_H_ */
 
 
 /* END */
diff --git a/src/psnames/psnamerr.h b/src/psnames/psnamerr.h
index acda7f9..3a9f653 100644
--- a/src/psnames/psnamerr.h
+++ b/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PS names module error codes (specification only).                    */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,12 +23,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __PSNAMERR_H__
-#define __PSNAMERR_H__
+#ifndef PSNAMERR_H_
+#define PSNAMERR_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  PSnames_Err_
@@ -36,7 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __PSNAMERR_H__ */
+#endif /* PSNAMERR_H_ */
 
 
 /* END */
diff --git a/src/psnames/psnames.c b/src/psnames/psnames.c
index 1ede225..e7b2c0b 100644
--- a/src/psnames/psnames.c
+++ b/src/psnames/psnames.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PSNames module component (body only).                       */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psnames/pspic.c b/src/psnames/pspic.c
index 3820f65..a78ec5a 100644
--- a/src/psnames/pspic.c
+++ b/src/psnames/pspic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for psnames module.  */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/psnames/pspic.h b/src/psnames/pspic.h
index 6ff002c..4834876 100644
--- a/src/psnames/pspic.h
+++ b/src/psnames/pspic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for psnames module.  */
 /*                                                                         */
-/*  Copyright 2009, 2012 by                                                */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,14 +16,13 @@
 /***************************************************************************/
 
 
-#ifndef __PSPIC_H__
-#define __PSPIC_H__
+#ifndef PSPIC_H_
+#define PSPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
 #define PSCMAPS_SERVICES_GET   pscmaps_services
@@ -33,6 +32,9 @@
 
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
+
+FT_BEGIN_HEADER
+
   typedef struct  PSModulePIC_
   {
     FT_ServiceDescRec*     pscmaps_services;
@@ -54,13 +56,13 @@
   FT_Error
   psnames_module_class_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
-FT_END_HEADER
-
-#endif /* __PSPIC_H__ */
+#endif /* PSPIC_H_ */
 
 
 /* END */
diff --git a/src/psnames/pstables.h b/src/psnames/pstables.h
index 0a6637f..eb827fa 100644
--- a/src/psnames/pstables.h
+++ b/src/psnames/pstables.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript glyph names.                                              */
 /*                                                                         */
-/*  Copyright 2005, 2008, 2011 by                                          */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 703155a..981ce32 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
 /*    Miscellaneous macros for stand-alone rasterizer (specification       */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 2005, 2009, 2010 by                                          */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -24,8 +24,8 @@
   /*                                                 */
   /***************************************************/
 
-#ifndef __FTMISC_H__
-#define __FTMISC_H__
+#ifndef FTMISC_H_
+#define FTMISC_H_
 
 
   /* memset */
@@ -37,7 +37,7 @@
 #define FT_LOCAL_DEF( x )   static x
 
 
-  /* from include/freetype2/fttypes.h */
+  /* from include/freetype/fttypes.h */
 
   typedef unsigned char  FT_Byte;
   typedef signed int     FT_Int;
@@ -54,7 +54,7 @@
               (FT_ULong)_x4         )
 
 
-  /* from include/freetype2/ftsystem.h */
+  /* from include/freetype/ftsystem.h */
 
   typedef struct FT_MemoryRec_*  FT_Memory;
 
@@ -136,7 +136,7 @@
     return ( s > 0 ) ? d : -d;
   }
 
-#endif /* __FTMISC_H__ */
+#endif /* FTMISC_H_ */
 
 
 /* END */
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index abbecb7..0fa2f26 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005, 2007-2014 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,18 +18,18 @@
   /*************************************************************************/
   /*                                                                       */
   /* This file can be compiled without the rest of the FreeType engine, by */
-  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
+  /* defining the STANDALONE_ macro when compiling it.  You also need to   */
   /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
   /* directory.  Typically, you should do something like                   */
   /*                                                                       */
   /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
   /*                                                                       */
-  /* - copy `include/ftimage.h' and `src/raster/ftmisc.h' to your current  */
-  /*   directory                                                           */
+  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
+  /*   current directory                                                   */
   /*                                                                       */
-  /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
+  /* - compile `ftraster' with the STANDALONE_ macro defined, as in        */
   /*                                                                       */
-  /*     cc -c -D_STANDALONE_ ftraster.c                                   */
+  /*     cc -c -DSTANDALONE_ ftraster.c                                    */
   /*                                                                       */
   /* The renderer can be initialized with a call to                        */
   /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
@@ -47,7 +47,11 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
+
+  /* The size in bytes of the render pool used by the scan-line converter  */
+  /* to do all of its work.                                                */
+#define FT_RENDER_POOL_SIZE  16384L
 
 #define FT_CONFIG_STANDARD_LIBRARY_H  <stdlib.h>
 
@@ -56,7 +60,7 @@
 #include "ftmisc.h"
 #include "ftimage.h"
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 #include <ft2build.h>
 #include "ftraster.h"
@@ -64,7 +68,7 @@
 
 #include "rastpic.h"
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
   /*************************************************************************/
@@ -150,14 +154,6 @@
   /* define DEBUG_RASTER if you want to compile a debugging version */
 /* #define DEBUG_RASTER */
 
-  /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
-  /* 5-levels anti-aliasing                                       */
-/* #define FT_RASTER_OPTION_ANTI_ALIASING */
-
-  /* The size of the two-lines intermediate bitmap used */
-  /* for anti-aliasing, in bytes.                       */
-#define RASTER_GRAY_LINES  2048
-
 
   /*************************************************************************/
   /*************************************************************************/
@@ -177,7 +173,7 @@
 #define FT_COMPONENT  trace_raster
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
   /* Auxiliary macros for token concatenation. */
 #define FT_ERR_XCAT( x, y )  x ## y
@@ -199,6 +195,7 @@
 #define FT_TRACE( x )   do { } while ( 0 )    /* nothing */
 #define FT_TRACE1( x )  do { } while ( 0 )    /* nothing */
 #define FT_TRACE6( x )  do { } while ( 0 )    /* nothing */
+#define FT_TRACE7( x )  do { } while ( 0 )    /* nothing */
 #endif
 
 #ifndef FT_THROW
@@ -227,7 +224,7 @@
             raster_done_                                            \
          };
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
 #include FT_INTERNAL_OBJECTS_H
@@ -243,7 +240,7 @@
 #define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
 
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
 #ifndef FT_MEM_SET
@@ -318,7 +315,7 @@
 
   typedef union  Alignment_
   {
-    long    l;
+    Long    l;
     void*   p;
     void  (*f)(void);
 
@@ -334,9 +331,9 @@
 
 
   /* values for the `flags' bit field */
-#define Flow_Up           0x8
-#define Overshoot_Top     0x10
-#define Overshoot_Bottom  0x20
+#define Flow_Up           0x08U
+#define Overshoot_Top     0x10U
+#define Overshoot_Bottom  0x20U
 
 
   /* States of each line, arc, and profile */
@@ -358,14 +355,14 @@
     FT_F26Dot6  X;           /* current coordinate during sweep          */
     PProfile    link;        /* link to next profile (various purposes)  */
     PLong       offset;      /* start of profile's data in render pool   */
-    unsigned    flags;       /* Bit 0-2: drop-out mode                   */
+    UShort      flags;       /* Bit 0-2: drop-out mode                   */
                              /* Bit 3: profile orientation (up/down)     */
                              /* Bit 4: is top profile?                   */
                              /* Bit 5: is bottom profile?                */
-    long        height;      /* profile's height in scanlines            */
-    long        start;       /* profile's starting scanline              */
+    Long        height;      /* profile's height in scanlines            */
+    Long        start;       /* profile's starting scanline              */
 
-    unsigned    countL;      /* number of lines to step before this      */
+    Int         countL;      /* number of lines to step before this      */
                              /* profile becomes drawable                 */
 
     PProfile    next;        /* next profile in same contour, used       */
@@ -387,7 +384,7 @@
 
 
 #define AlignProfileSize \
-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
+  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
 
 
 #undef RAS_ARG
@@ -451,13 +448,21 @@
 #define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
 #define TRUNC( x )    ( (Long)(x) >> ras.precision_bits )
 #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x )   ( ( (ULong)(x) << ras.scale_shift ) - ras.precision_half )
+#define SCALED( x )   ( ( (x) < 0 ? -( -(x) << ras.scale_shift )   \
+                                  :  (  (x) << ras.scale_shift ) ) \
+                        - 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 )
 
+#if FT_RENDER_POOL_SIZE > 2048
+#define FT_MAX_BLACK_POOL  ( FT_RENDER_POOL_SIZE / sizeof ( Long ) )
+#else
+#define FT_MAX_BLACK_POOL  ( 2048 / sizeof ( Long ) )
+#endif
+
   /* The most used variables are positioned at the top of the structure. */
   /* Thus, their offset can be coded with less opcodes, resulting in a   */
   /* smaller executable.                                                 */
@@ -514,9 +519,6 @@
 
     Short       traceIncr;          /* sweep's increment in target bitmap  */
 
-    Short       gray_min_x;         /* current min x during gray rendering */
-    Short       gray_max_x;         /* current max x during gray rendering */
-
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;
@@ -529,45 +531,19 @@
     Bool        second_pass;        /* indicates whether a horizontal pass */
                                     /* should be performed to control      */
                                     /* drop-out accurately when calling    */
-                                    /* Render_Glyph.  Note that there is   */
-                                    /* no horizontal pass during gray      */
-                                    /* rendering.                          */
+                                    /* Render_Glyph.                       */
 
     TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
 
     black_TBand  band_stack[16];    /* band stack used for sub-banding     */
     Int          band_top;          /* band stack top                      */
 
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-    Byte*       grays;
-
-    Byte        gray_lines[RASTER_GRAY_LINES];
-                                /* Intermediate table used to render the   */
-                                /* graylevels pixmaps.                     */
-                                /* gray_lines is a buffer holding two      */
-                                /* monochrome scanlines                    */
-
-    Short       gray_width;     /* width in bytes of one monochrome        */
-                                /* intermediate scanline of gray_lines.    */
-                                /* Each gray pixel takes 2 bits long there */
-
-                       /* The gray_lines must hold 2 lines, thus with size */
-                       /* in bytes of at least `gray_width*2'.             */
-
-#endif /* FT_RASTER_ANTI_ALIASING */
-
   };
 
 
   typedef struct  black_TRaster_
   {
-    char*          buffer;
-    long           buffer_size;
     void*          memory;
-    black_PWorker  worker;
-    Byte           grays[5];
-    Short          gray_width;
 
   } black_TRaster, *black_PRaster;
 
@@ -583,70 +559,6 @@
 #endif /* !FT_STATIC_RASTER */
 
 
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-  /* A lookup table used to quickly count set bits in four gray 2x2 */
-  /* cells.  The values of the table have been produced with the    */
-  /* following code:                                                */
-  /*                                                                */
-  /*   for ( i = 0; i < 256; i++ )                                  */
-  /*   {                                                            */
-  /*     l = 0;                                                     */
-  /*     j = i;                                                     */
-  /*                                                                */
-  /*     for ( c = 0; c < 4; c++ )                                  */
-  /*     {                                                          */
-  /*       l <<= 4;                                                 */
-  /*                                                                */
-  /*       if ( j & 0x80 ) l++;                                     */
-  /*       if ( j & 0x40 ) l++;                                     */
-  /*                                                                */
-  /*       j = ( j << 2 ) & 0xFF;                                   */
-  /*     }                                                          */
-  /*     printf( "0x%04X", l );                                     */
-  /*   }                                                            */
-  /*                                                                */
-
-  static const short  count_table[256] =
-  {
-    0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
-    0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
-    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
-    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
-    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
-    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
-    0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
-    0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
-    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
-    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
-    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
-    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
-    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
-    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
-    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
-    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
-    0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
-    0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
-    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
-    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
-    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
-    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
-    0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
-    0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
-  };
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
-
   /*************************************************************************/
   /*************************************************************************/
   /**                                                                     **/
@@ -677,11 +589,11 @@
      * approximating it as a straight segment.  The default value of 32 (for
      * low accuracy) corresponds to
      *
-     *   32 / 64 == 0.5 pixels ,
+     *   32 / 64 == 0.5 pixels,
      *
      * while for the high accuracy case we have
      *
-     *   256/ (1 << 12) = 0.0625 pixels .
+     *   256 / (1 << 12) = 0.0625 pixels.
      *
      * `precision_jitter' is an epsilon threshold used in
      * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
@@ -764,13 +676,13 @@
       if ( overshoot )
         ras.cProfile->flags |= Overshoot_Bottom;
 
-      FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));
+      FT_TRACE6(( "  new ascending profile = %p\n", ras.cProfile ));
       break;
 
     case Descending_State:
       if ( overshoot )
         ras.cProfile->flags |= Overshoot_Top;
-      FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
+      FT_TRACE6(( "  new descending profile = %p\n", ras.cProfile ));
       break;
 
     default:
@@ -825,7 +737,7 @@
       PProfile  oldProfile;
 
 
-      FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
+      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
                   ras.cProfile, ras.cProfile->start, h ));
 
       ras.cProfile->height = h;
@@ -893,15 +805,14 @@
 
     /* if it is <, simply insert it, ignore if == */
     if ( n >= 0 && y > y_turns[n] )
-      while ( n >= 0 )
+      do
       {
         Int  y2 = (Int)y_turns[n];
 
 
         y_turns[n] = y;
         y = y2;
-        n--;
-      }
+      } while ( --n >= 0 );
 
     if ( n < 0 )
     {
@@ -942,7 +853,7 @@
 
     if ( n > 1 && p )
     {
-      while ( n > 0 )
+      do
       {
         Int  bottom, top;
 
@@ -970,8 +881,7 @@
           return FAILURE;
 
         p = p->link;
-        n--;
-      }
+      } while ( --n );
     }
     else
       ras.fProfile = NULL;
@@ -1342,7 +1252,7 @@
 
     start_arc = arc;
 
-    while ( arc >= start_arc && e <= e2 )
+    do
     {
       ras.joint = FALSE;
 
@@ -1375,7 +1285,7 @@
         }
         arc -= degree;
       }
-    }
+    } while ( arc >= start_arc && e <= e2 );
 
   Fin:
     ras.top  = top;
@@ -1813,7 +1723,7 @@
   static Bool
   Decompose_Curve( RAS_ARGS UShort  first,
                             UShort  last,
-                            int     flipped )
+                            Int     flipped )
   {
     FT_Vector   v_last;
     FT_Vector   v_control;
@@ -1824,7 +1734,7 @@
     FT_Vector*  limit;
     char*       tags;
 
-    unsigned    tag;       /* current point's state           */
+    UInt        tag;       /* current point's state           */
 
 
     points = ras.outline.points;
@@ -2035,10 +1945,10 @@
   /*    rendering.                                                         */
   /*                                                                       */
   static Bool
-  Convert_Glyph( RAS_ARGS int  flipped )
+  Convert_Glyph( RAS_ARGS Int  flipped )
   {
-    int       i;
-    unsigned  start;
+    Int   i;
+    UInt  start;
 
 
     ras.fProfile = NULL;
@@ -2064,12 +1974,12 @@
       ras.state    = Unknown_State;
       ras.gProfile = NULL;
 
-      if ( Decompose_Curve( RAS_VARS (unsigned short)start,
-                                     ras.outline.contours[i],
+      if ( Decompose_Curve( RAS_VARS (UShort)start,
+                                     (UShort)ras.outline.contours[i],
                                      flipped ) )
         return FAILURE;
 
-      start = ras.outline.contours[i] + 1;
+      start = (UShort)ras.outline.contours[i] + 1;
 
       /* we must now check whether the extreme arcs join or not */
       if ( FRAC( ras.lastY ) == 0 &&
@@ -2083,7 +1993,8 @@
         /* to be drawn.                                                   */
 
       lastProfile = ras.cProfile;
-      if ( ras.cProfile->flags & Flow_Up )
+      if ( ras.top != ras.cProfile->offset &&
+           ( ras.cProfile->flags & Flow_Up ) )
         o = IS_TOP_OVERSHOOT( ras.lastY );
       else
         o = IS_BOTTOM_OVERSHOOT( ras.lastY );
@@ -2207,7 +2118,7 @@
     while ( current )
     {
       current->X       = *current->offset;
-      current->offset += current->flags & Flow_Up ? 1 : -1;
+      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
       current->height--;
       current = current->link;
     }
@@ -2267,10 +2178,7 @@
     ras.traceIncr = (Short)-pitch;
     ras.traceOfs  = -*min * pitch;
     if ( pitch > 0 )
-      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
-
-    ras.gray_min_x = 0;
-    ras.gray_max_x = 0;
+      ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
   }
 
 
@@ -2291,6 +2199,14 @@
     FT_UNUSED( right );
 
 
+    /* in high-precision mode, we need 12 digits after the comma to */
+    /* represent multiples of 1/(1<<12) = 1/4096                    */
+    FT_TRACE7(( "  y=%d x=[%.12f;%.12f], drop-out=%d",
+                y,
+                x1 / (double)ras.precision,
+                x2 / (double)ras.precision,
+                dropOutControl ));
+
     /* Drop-out control */
 
     e1 = TRUNC( CEILING( x1 ) );
@@ -2303,7 +2219,7 @@
 
     if ( e2 >= 0 && e1 < ras.bWidth )
     {
-      int   c1, c2;
+      Int   c1, c2;
       Byte  f1, f2;
 
 
@@ -2312,17 +2228,14 @@
       if ( e2 >= ras.bWidth )
         e2 = ras.bWidth - 1;
 
+      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
+
       c1 = (Short)( e1 >> 3 );
       c2 = (Short)( e2 >> 3 );
 
       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
 
-      if ( ras.gray_min_x > c1 )
-        ras.gray_min_x = (short)c1;
-      if ( ras.gray_max_x < c2 )
-        ras.gray_max_x = (short)c2;
-
       target = ras.bTarget + ras.traceOfs + c1;
       c2 -= c1;
 
@@ -2344,6 +2257,8 @@
       else
         *target |= ( f1 & f2 );
     }
+
+    FT_TRACE7(( "\n" ));
   }
 
 
@@ -2358,6 +2273,11 @@
     Short  c1, f1;
 
 
+    FT_TRACE7(( "  y=%d x=[%.12f;%.12f]",
+                y,
+                x1 / (double)ras.precision,
+                x2 / (double)ras.precision ));
+
     /* Drop-out control */
 
     /*   e2            x2                    x1           e1   */
@@ -2390,6 +2310,8 @@
       Int  dropOutControl = left->flags & 7;
 
 
+      FT_TRACE7(( ", drop-out=%d", dropOutControl ));
+
       if ( e1 == e2 + ras.precision )
       {
         switch ( dropOutControl )
@@ -2436,14 +2358,14 @@
                left->height <= 0                  &&
                !( left->flags & Overshoot_Top   &&
                   x2 - x1 >= ras.precision_half ) )
-            return;
+            goto Exit;
 
           /* lower stub test */
           if ( right->next == left                 &&
                left->start == y                    &&
                !( left->flags & Overshoot_Bottom &&
                   x2 - x1 >= ras.precision_half  ) )
-            return;
+            goto Exit;
 
           if ( dropOutControl == 1 )
             pxl = e2;
@@ -2452,7 +2374,7 @@
           break;
 
         default: /* modes 2, 3, 6, 7 */
-          return;  /* no drop-out control */
+          goto Exit;  /* no drop-out control */
         }
 
         /* undocumented but confirmed: If the drop-out would result in a  */
@@ -2473,26 +2395,26 @@
 
         if ( e1 >= 0 && e1 < ras.bWidth                      &&
              ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
-          return;
+          goto Exit;
       }
       else
-        return;
+        goto Exit;
     }
 
     e1 = TRUNC( pxl );
 
     if ( e1 >= 0 && e1 < ras.bWidth )
     {
+      FT_TRACE7(( " -> x=%d (drop-out)", e1 ));
+
       c1 = (Short)( e1 >> 3 );
       f1 = (Short)( e1 & 7 );
 
-      if ( ras.gray_min_x > c1 )
-        ras.gray_min_x = c1;
-      if ( ras.gray_max_x < c1 )
-        ras.gray_max_x = c1;
-
       ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
     }
+
+  Exit:
+    FT_TRACE7(( "\n" ));
   }
 
 
@@ -2539,32 +2461,39 @@
       Long  e1, e2;
 
 
+      FT_TRACE7(( "  x=%d y=[%.12f;%.12f]",
+                  y,
+                  x1 / (double)ras.precision,
+                  x2 / (double)ras.precision ));
+
       e1 = CEILING( x1 );
       e2 = FLOOR  ( x2 );
 
       if ( e1 == e2 )
       {
-        Byte   f1;
-        PByte  bits;
-
-
-        bits = ras.bTarget + ( y >> 3 );
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
-
         e1 = TRUNC( e1 );
 
-        if ( e1 >= 0 && e1 < ras.target.rows )
+        if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
         {
+          Byte   f1;
+          PByte  bits;
           PByte  p;
 
 
-          p = bits - e1 * ras.target.pitch;
+          FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
+
+          bits = ras.bTarget + ( y >> 3 );
+          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+          p    = bits - e1 * ras.target.pitch;
+
           if ( ras.target.pitch > 0 )
-            p += ( ras.target.rows - 1 ) * ras.target.pitch;
+            p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
           p[0] |= f1;
         }
       }
+
+      FT_TRACE7(( "\n" ));
     }
   }
 
@@ -2581,6 +2510,11 @@
     Byte   f1;
 
 
+    FT_TRACE7(( "  x=%d y=[%.12f;%.12f]",
+                y,
+                x1 / (double)ras.precision,
+                x2 / (double)ras.precision ));
+
     /* During the horizontal sweep, we only take care of drop-outs */
 
     /* e1     +       <-- pixel center */
@@ -2602,6 +2536,8 @@
       Int  dropOutControl = left->flags & 7;
 
 
+      FT_TRACE7(( ", dropout=%d", dropOutControl ));
+
       if ( e1 == e2 + ras.precision )
       {
         switch ( dropOutControl )
@@ -2623,14 +2559,14 @@
                left->height <= 0                  &&
                !( left->flags & Overshoot_Top   &&
                   x2 - x1 >= ras.precision_half ) )
-            return;
+            goto Exit;
 
           /* leftmost stub test */
           if ( right->next == left                 &&
                left->start == y                    &&
                !( left->flags & Overshoot_Bottom &&
                   x2 - x1 >= ras.precision_half  ) )
-            return;
+            goto Exit;
 
           if ( dropOutControl == 1 )
             pxl = e2;
@@ -2639,7 +2575,7 @@
           break;
 
         default: /* modes 2, 3, 6, 7 */
-          return;  /* no drop-out control */
+          goto Exit;  /* no drop-out control */
         }
 
         /* undocumented but confirmed: If the drop-out would result in a  */
@@ -2647,7 +2583,7 @@
         /* bounding box instead                                           */
         if ( pxl < 0 )
           pxl = e1;
-        else if ( TRUNC( pxl ) >= ras.target.rows )
+        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
           pxl = e2;
 
         /* check that the other pixel isn't set */
@@ -2660,30 +2596,35 @@
 
         bits -= e1 * ras.target.pitch;
         if ( ras.target.pitch > 0 )
-          bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+          bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
-        if ( e1 >= 0              &&
-             e1 < ras.target.rows &&
-             *bits & f1           )
-          return;
+        if ( e1 >= 0                     &&
+             (ULong)e1 < ras.target.rows &&
+             *bits & f1                  )
+          goto Exit;
       }
       else
-        return;
+        goto Exit;
     }
 
-    bits = ras.bTarget + ( y >> 3 );
-    f1   = (Byte)( 0x80 >> ( y & 7 ) );
-
     e1 = TRUNC( pxl );
 
-    if ( e1 >= 0 && e1 < ras.target.rows )
+    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
     {
+      FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
+
+      bits  = ras.bTarget + ( y >> 3 );
+      f1    = (Byte)( 0x80 >> ( y & 7 ) );
       bits -= e1 * ras.target.pitch;
+
       if ( ras.target.pitch > 0 )
-        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+        bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
       bits[0] |= f1;
     }
+
+  Exit:
+    FT_TRACE7(( "\n" ));
   }
 
 
@@ -2695,249 +2636,6 @@
   }
 
 
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Vertical Gray Sweep Procedure Set                                    */
-  /*                                                                       */
-  /*  These two routines are used during the vertical gray-levels sweep    */
-  /*  phase by the generic Draw_Sweep() function.                          */
-  /*                                                                       */
-  /*  NOTES                                                                */
-  /*                                                                       */
-  /*  - The target pixmap's width *must* be a multiple of 4.               */
-  /*                                                                       */
-  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
-  /*    span call.                                                         */
-  /*                                                                       */
-  /*************************************************************************/
-
-  static void
-  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
-                                     Short*  max )
-  {
-    Long  pitch, byte_len;
-
-
-    *min = *min & -2;
-    *max = ( *max + 3 ) & -2;
-
-    ras.traceOfs  = 0;
-    pitch         = ras.target.pitch;
-    byte_len      = -pitch;
-    ras.traceIncr = (Short)byte_len;
-    ras.traceG    = ( *min / 2 ) * byte_len;
-
-    if ( pitch > 0 )
-    {
-      ras.traceG += ( ras.target.rows - 1 ) * pitch;
-      byte_len    = -byte_len;
-    }
-
-    ras.gray_min_x =  (Short)byte_len;
-    ras.gray_max_x = -(Short)byte_len;
-  }
-
-
-  static void
-  Vertical_Gray_Sweep_Step( RAS_ARG )
-  {
-    short*  count = (short*)count_table;
-    Byte*   grays;
-
-
-    ras.traceOfs += ras.gray_width;
-
-    if ( ras.traceOfs > ras.gray_width )
-    {
-      PByte  pix;
-
-
-      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
-      grays = ras.grays;
-
-      if ( ras.gray_max_x >= 0 )
-      {
-        Long  last_pixel = ras.target.width - 1;
-        Int   last_cell  = last_pixel >> 2;
-        Int   last_bit   = last_pixel & 3;
-        Bool  over       = 0;
-
-        Int    c1, c2;
-        PByte  bit, bit2;
-
-
-        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
-        {
-          ras.gray_max_x = last_cell - 1;
-          over = 1;
-        }
-
-        if ( ras.gray_min_x < 0 )
-          ras.gray_min_x = 0;
-
-        bit  = ras.bTarget + ras.gray_min_x;
-        bit2 = bit + ras.gray_width;
-
-        c1 = ras.gray_max_x - ras.gray_min_x;
-
-        while ( c1 >= 0 )
-        {
-          c2 = count[*bit] + count[*bit2];
-
-          if ( c2 )
-          {
-            pix[0] = grays[(c2 >> 12) & 0x000F];
-            pix[1] = grays[(c2 >> 8 ) & 0x000F];
-            pix[2] = grays[(c2 >> 4 ) & 0x000F];
-            pix[3] = grays[ c2        & 0x000F];
-
-            *bit  = 0;
-            *bit2 = 0;
-          }
-
-          bit++;
-          bit2++;
-          pix += 4;
-          c1--;
-        }
-
-        if ( over )
-        {
-          c2 = count[*bit] + count[*bit2];
-          if ( c2 )
-          {
-            switch ( last_bit )
-            {
-            case 2:
-              pix[2] = grays[(c2 >> 4 ) & 0x000F];
-            case 1:
-              pix[1] = grays[(c2 >> 8 ) & 0x000F];
-            default:
-              pix[0] = grays[(c2 >> 12) & 0x000F];
-            }
-
-            *bit  = 0;
-            *bit2 = 0;
-          }
-        }
-      }
-
-      ras.traceOfs = 0;
-      ras.traceG  += ras.traceIncr;
-
-      ras.gray_min_x =  32000;
-      ras.gray_max_x = -32000;
-    }
-  }
-
-
-  static void
-  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
-                                       FT_F26Dot6  x1,
-                                       FT_F26Dot6  x2,
-                                       PProfile    left,
-                                       PProfile    right )
-  {
-    /* nothing, really */
-    FT_UNUSED_RASTER;
-    FT_UNUSED( y );
-    FT_UNUSED( x1 );
-    FT_UNUSED( x2 );
-    FT_UNUSED( left );
-    FT_UNUSED( right );
-  }
-
-
-  static void
-  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
-                                       FT_F26Dot6  x1,
-                                       FT_F26Dot6  x2,
-                                       PProfile    left,
-                                       PProfile    right )
-  {
-    Long   e1, e2;
-    PByte  pixel;
-
-
-    /* During the horizontal sweep, we only take care of drop-outs */
-
-    e1 = CEILING( x1 );
-    e2 = FLOOR  ( x2 );
-
-    if ( e1 > e2 )
-    {
-      Int  dropOutControl = left->flags & 7;
-
-
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          e1 = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-          /* see Vertical_Sweep_Drop for details */
-
-          /* rightmost stub test */
-          if ( left->next == right && left->height <= 0 )
-            return;
-
-          /* leftmost stub test */
-          if ( right->next == left && left->start == y )
-            return;
-
-          if ( dropOutControl == 1 )
-            e1 = e2;
-          else
-            e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
-
-          break;
-
-        default: /* modes 2, 3, 6, 7 */
-          return;  /* no drop-out control */
-        }
-      }
-      else
-        return;
-    }
-
-    if ( e1 >= 0 )
-    {
-      Byte  color;
-
-
-      if ( x2 - x1 >= ras.precision_half )
-        color = ras.grays[2];
-      else
-        color = ras.grays[1];
-
-      e1 = TRUNC( e1 ) / 2;
-      if ( e1 < ras.target.rows )
-      {
-        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
-        if ( ras.target.pitch > 0 )
-          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
-
-        if ( pixel[0] == ras.grays[0] )
-          pixel[0] = color;
-      }
-    }
-  }
-
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
   /*************************************************************************/
   /*                                                                       */
   /*  Generic Sweep Drawing routine                                        */
@@ -3007,7 +2705,7 @@
 
     while ( P )
     {
-      P->countL = (UShort)( P->start - min_Y );
+      P->countL = P->start - min_Y;
       P = P->link;
     }
 
@@ -3270,7 +2968,7 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  static FT_Error
   Render_Glyph( RAS_ARG )
   {
     FT_Error  error;
@@ -3293,10 +2991,12 @@
         ras.dropOutControl += 1;
     }
 
-    ras.second_pass = (FT_Byte)( !( ras.outline.flags &
-                                    FT_OUTLINE_SINGLE_PASS ) );
+    ras.second_pass = (Bool)( !( ras.outline.flags      &
+                                 FT_OUTLINE_SINGLE_PASS ) );
 
     /* Vertical Sweep */
+    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
+
     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
@@ -3304,9 +3004,9 @@
 
     ras.band_top            = 0;
     ras.band_stack[0].y_min = 0;
-    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
+    ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
 
-    ras.bWidth  = (unsigned short)ras.target.width;
+    ras.bWidth  = (UShort)ras.target.width;
     ras.bTarget = (Byte*)ras.target.buffer;
 
     if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
@@ -3315,6 +3015,8 @@
     /* Horizontal Sweep */
     if ( ras.second_pass && ras.dropOutControl != 2 )
     {
+      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
+
       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
@@ -3322,7 +3024,7 @@
 
       ras.band_top            = 0;
       ras.band_stack[0].y_min = 0;
-      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
+      ras.band_stack[0].y_max = (Short)( ras.target.width - 1 );
 
       if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
         return error;
@@ -3332,118 +3034,10 @@
   }
 
 
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Render_Gray_Glyph                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Render a glyph with grayscaling.  Sub-banding if needed.           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  Render_Gray_Glyph( RAS_ARG )
-  {
-    Long      pixel_width;
-    FT_Error  error;
-
-
-    Set_High_Precision( RAS_VARS ras.outline.flags &
-                                 FT_OUTLINE_HIGH_PRECISION );
-    ras.scale_shift = ras.precision_shift + 1;
-
-    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
-      ras.dropOutControl = 2;
-    else
-    {
-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
-        ras.dropOutControl = 4;
-      else
-        ras.dropOutControl = 0;
-
-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
-        ras.dropOutControl += 1;
-    }
-
-    ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
-
-    /* Vertical Sweep */
-
-    ras.band_top            = 0;
-    ras.band_stack[0].y_min = 0;
-    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
-
-    ras.bWidth  = ras.gray_width;
-    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
-
-    if ( ras.bWidth > pixel_width )
-      ras.bWidth = pixel_width;
-
-    ras.bWidth  = ras.bWidth * 8;
-    ras.bTarget = (Byte*)ras.gray_lines;
-    ras.gTarget = (Byte*)ras.target.buffer;
-
-    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
-    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
-    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
-    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
-
-    error = Render_Single_Pass( RAS_VARS 0 );
-    if ( error )
-      return error;
-
-    /* Horizontal Sweep */
-    if ( ras.second_pass && ras.dropOutControl != 2 )
-    {
-      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
-      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
-      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
-      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
-
-      ras.band_top            = 0;
-      ras.band_stack[0].y_min = 0;
-      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
-
-      error = Render_Single_Pass( RAS_VARS 1 );
-      if ( error )
-        return error;
-    }
-
-    return Raster_Err_None;
-  }
-
-#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
-
-  FT_LOCAL_DEF( FT_Error )
-  Render_Gray_Glyph( RAS_ARG )
-  {
-    FT_UNUSED_RASTER;
-
-    return FT_THROW( Unsupported );
-  }
-
-#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
-
-
   static void
   ft_black_init( black_PRaster  raster )
   {
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-    FT_UInt  n;
-
-
-    /* set default 5-levels gray palette */
-    for ( n = 0; n < 5; n++ )
-      raster->grays[n] = n * 255 / 4;
-
-    raster->gray_width = RASTER_GRAY_LINES / 2;
-#else
     FT_UNUSED( raster );
-#endif
   }
 
 
@@ -3451,7 +3045,7 @@
   /****                         a static object.                  *****/
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
 
   static int
@@ -3478,7 +3072,7 @@
   }
 
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
   static int
@@ -3512,73 +3106,46 @@
   }
 
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
   static void
-  ft_black_reset( black_PRaster  raster,
-                  char*          pool_base,
-                  long           pool_size )
+  ft_black_reset( FT_Raster  raster,
+                  PByte      pool_base,
+                  ULong      pool_size )
   {
-    if ( raster )
-    {
-      if ( pool_base && pool_size >= (long)sizeof ( black_TWorker ) + 2048 )
-      {
-        black_PWorker  worker = (black_PWorker)pool_base;
-
-
-        raster->buffer      = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );
-        raster->buffer_size = (long)( pool_base + pool_size -
-                                        (char*)raster->buffer );
-        raster->worker      = worker;
-      }
-      else
-      {
-        raster->buffer      = NULL;
-        raster->buffer_size = 0;
-        raster->worker      = NULL;
-      }
-    }
-  }
-
-
-  static void
-  ft_black_set_mode( black_PRaster  raster,
-                     unsigned long  mode,
-                     const char*    palette )
-  {
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
-    {
-      /* set 5-levels gray palette */
-      raster->grays[0] = palette[0];
-      raster->grays[1] = palette[1];
-      raster->grays[2] = palette[2];
-      raster->grays[3] = palette[3];
-      raster->grays[4] = palette[4];
-    }
-
-#else
-
     FT_UNUSED( raster );
-    FT_UNUSED( mode );
-    FT_UNUSED( palette );
-
-#endif
+    FT_UNUSED( pool_base );
+    FT_UNUSED( pool_size );
   }
 
 
   static int
-  ft_black_render( black_PRaster            raster,
+  ft_black_set_mode( FT_Raster  raster,
+                     ULong      mode,
+                     void*      args )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( args );
+
+    return 0;
+  }
+
+
+  static int
+  ft_black_render( FT_Raster                raster,
                    const FT_Raster_Params*  params )
   {
     const FT_Outline*  outline    = (const FT_Outline*)params->source;
     const FT_Bitmap*   target_map = params->target;
-    black_PWorker      worker;
+
+    black_TWorker  worker[1];
+
+    Long  buffer[FT_MAX_BLACK_POOL];
 
 
-    if ( !raster || !raster->buffer || !raster->buffer_size )
+    if ( !raster )
       return FT_THROW( Not_Ini );
 
     if ( !outline )
@@ -3595,12 +3162,13 @@
            outline->contours[outline->n_contours - 1] + 1 )
       return FT_THROW( Invalid );
 
-    worker = raster->worker;
-
     /* this version of the raster does not support direct rendering, sorry */
     if ( params->flags & FT_RASTER_FLAG_DIRECT )
       return FT_THROW( Unsupported );
 
+    if ( params->flags & FT_RASTER_FLAG_AA )
+      return FT_THROW( Unsupported );
+
     if ( !target_map )
       return FT_THROW( Invalid );
 
@@ -3611,33 +3179,40 @@
     if ( !target_map->buffer )
       return FT_THROW( Invalid );
 
+    /* reject too large outline coordinates */
+    {
+      FT_Vector*  vec   = outline->points;
+      FT_Vector*  limit = vec + outline->n_points;
+
+
+      for ( ; vec < limit; vec++ )
+      {
+        if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
+             vec->y < -0x1000000L || vec->y > 0x1000000L )
+         return FT_THROW( Invalid );
+      }
+    }
+
     ras.outline = *outline;
     ras.target  = *target_map;
 
-    worker->buff       = (PLong) raster->buffer;
-    worker->sizeBuff   = worker->buff +
-                           raster->buffer_size / sizeof ( Long );
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-    worker->grays      = raster->grays;
-    worker->gray_width = raster->gray_width;
+    worker->buff     = buffer;
+    worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
 
-    FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
-#endif
-
-    return ( params->flags & FT_RASTER_FLAG_AA )
-           ? Render_Gray_Glyph( RAS_VAR )
-           : Render_Glyph( RAS_VAR );
+    return Render_Glyph( RAS_VAR );
   }
 
 
-  FT_DEFINE_RASTER_FUNCS( ft_standard_raster,
+  FT_DEFINE_RASTER_FUNCS(
+    ft_standard_raster,
+
     FT_GLYPH_FORMAT_OUTLINE,
+
     (FT_Raster_New_Func)     ft_black_new,
     (FT_Raster_Reset_Func)   ft_black_reset,
     (FT_Raster_Set_Mode_Func)ft_black_set_mode,
     (FT_Raster_Render_Func)  ft_black_render,
-    (FT_Raster_Done_Func)    ft_black_done
-  )
+    (FT_Raster_Done_Func)    ft_black_done )
 
 
 /* END */
diff --git a/src/raster/ftraster.h b/src/raster/ftraster.h
index 80fe46d..65cd5f9 100644
--- a/src/raster/ftraster.h
+++ b/src/raster/ftraster.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (specification).                       */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTRASTER_H__
-#define __FTRASTER_H__
+#ifndef FTRASTER_H_
+#define FTRASTER_H_
 
 
 #include <ft2build.h>
@@ -33,14 +33,14 @@
   /* Uncomment the following line if you are using ftraster.c as a         */
   /* standalone module, fully independent of FreeType.                     */
   /*                                                                       */
-/* #define _STANDALONE_ */
+/* #define STANDALONE_ */
 
   FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_standard_raster;
 
 
 FT_END_HEADER
 
-#endif /* __FTRASTER_H__ */
+#endif /* FTRASTER_H_ */
 
 
 /* END */
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index aa7f6d5..494f112 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer interface (body).                      */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005, 2006, 2011, 2013 by                         */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -104,7 +104,7 @@
   {
     FT_Error     error;
     FT_Outline*  outline;
-    FT_BBox      cbox;
+    FT_BBox      cbox, cbox0;
     FT_UInt      width, height, pitch;
     FT_Bitmap*   bitmap;
     FT_Memory    memory;
@@ -120,38 +120,11 @@
     }
 
     /* check rendering mode */
-#ifndef FT_CONFIG_OPTION_PIC
     if ( mode != FT_RENDER_MODE_MONO )
     {
       /* raster1 is only capable of producing monochrome bitmaps */
-      if ( render->clazz == &ft_raster1_renderer_class )
-        return FT_THROW( Cannot_Render_Glyph );
+      return FT_THROW( Cannot_Render_Glyph );
     }
-    else
-    {
-      /* raster5 is only capable of producing 5-gray-levels bitmaps */
-      if ( render->clazz == &ft_raster5_renderer_class )
-        return FT_THROW( Cannot_Render_Glyph );
-    }
-#else /* FT_CONFIG_OPTION_PIC */
-    /* When PIC is enabled, we cannot get to the class object      */
-    /* so instead we check the final character in the class name   */
-    /* ("raster5" or "raster1"). Yes this is a hack.               */
-    /* The "correct" thing to do is have different render function */
-    /* for each of the classes.                                    */
-    if ( mode != FT_RENDER_MODE_MONO )
-    {
-      /* raster1 is only capable of producing monochrome bitmaps */
-      if ( render->clazz->root.module_name[6] == '1' )
-        return FT_THROW( Cannot_Render_Glyph );
-    }
-    else
-    {
-      /* raster5 is only capable of producing 5-gray-levels bitmaps */
-      if ( render->clazz->root.module_name[6] == '5' )
-        return FT_THROW( Cannot_Render_Glyph );
-    }
-#endif /* FT_CONFIG_OPTION_PIC */
 
     outline = &slot->outline;
 
@@ -160,14 +133,14 @@
       FT_Outline_Translate( outline, origin->x, origin->y );
 
     /* compute the control box, and grid fit it */
-    FT_Outline_Get_CBox( outline, &cbox );
+    FT_Outline_Get_CBox( outline, &cbox0 );
 
     /* undocumented but confirmed: bbox values get rounded */
 #if 1
-    cbox.xMin = FT_PIX_ROUND( cbox.xMin );
-    cbox.yMin = FT_PIX_ROUND( cbox.yMin );
-    cbox.xMax = FT_PIX_ROUND( cbox.xMax );
-    cbox.yMax = FT_PIX_ROUND( cbox.yMax );
+    cbox.xMin = FT_PIX_ROUND( cbox0.xMin );
+    cbox.yMin = FT_PIX_ROUND( cbox0.yMin );
+    cbox.xMax = FT_PIX_ROUND( cbox0.xMax );
+    cbox.yMax = FT_PIX_ROUND( cbox0.yMax );
 #else
     cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
     cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
@@ -175,8 +148,28 @@
     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
 #endif
 
+    /* If either `width' or `height' round to 0, try    */
+    /* explicitly rounding up/down.  In the case of     */
+    /* glyphs containing only one very narrow feature,  */
+    /* this gives the drop-out compensation in the scan */
+    /* conversion code a chance to do its stuff.        */
     width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+    if ( width == 0 )
+    {
+      cbox.xMin = FT_PIX_FLOOR( cbox0.xMin );
+      cbox.xMax = FT_PIX_CEIL( cbox0.xMax );
+
+      width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+    }
+
     height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+    if ( height == 0 )
+    {
+      cbox.yMin = FT_PIX_FLOOR( cbox0.yMin );
+      cbox.yMax = FT_PIX_CEIL( cbox0.yMax );
+
+      height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+    }
 
     if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
     {
@@ -194,23 +187,12 @@
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
-    /* allocate new one, depends on pixel format */
-    if ( !( mode & FT_RENDER_MODE_MONO ) )
-    {
-      /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
-      pitch              = FT_PAD_CEIL( width, 4 );
-      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
-      bitmap->num_grays  = 256;
-    }
-    else
-    {
-      pitch              = ( ( width + 15 ) >> 4 ) << 1;
-      bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
-    }
+    pitch              = ( ( width + 15 ) >> 4 ) << 1;
+    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
 
     bitmap->width = width;
     bitmap->rows  = height;
-    bitmap->pitch = pitch;
+    bitmap->pitch = (int)pitch;
 
     if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) )
       goto Exit;
@@ -225,9 +207,6 @@
     params.source = outline;
     params.flags  = 0;
 
-    if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY )
-      params.flags |= FT_RASTER_FLAG_AA;
-
     /* render outline into the bitmap */
     error = render->raster_render( render->raster, &params );
 
@@ -272,35 +251,4 @@
   )
 
 
-  /* This renderer is _NOT_ part of the default modules; you will need */
-  /* to register it by hand in your application.  It should only be    */
-  /* used for backwards-compatibility with FT 1.x anyway.              */
-  /*                                                                   */
-  FT_DEFINE_RENDERER( ft_raster5_renderer_class,
-
-      FT_MODULE_RENDERER,
-      sizeof ( FT_RendererRec ),
-
-      "raster5",
-      0x10000L,
-      0x20000L,
-
-      0,    /* module specific interface */
-
-      (FT_Module_Constructor)ft_raster1_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
-
-    FT_GLYPH_FORMAT_OUTLINE,
-
-    (FT_Renderer_RenderFunc)   ft_raster1_render,
-    (FT_Renderer_TransformFunc)ft_raster1_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_raster1_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_raster1_set_mode,
-
-    (FT_Raster_Funcs*)    &FT_STANDARD_RASTER_GET
-  )
-
-
 /* END */
diff --git a/src/raster/ftrend1.h b/src/raster/ftrend1.h
index 4cf1286..a431f18 100644
--- a/src/raster/ftrend1.h
+++ b/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer interface (specification).             */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTREND1_H__
-#define __FTREND1_H__
+#ifndef FTREND1_H_
+#define FTREND1_H_
 
 
 #include <ft2build.h>
@@ -29,16 +29,10 @@
 
   FT_DECLARE_RENDERER( ft_raster1_renderer_class )
 
-  /* this renderer is _NOT_ part of the default modules, you'll need */
-  /* to register it by hand in your application.  It should only be  */
-  /* used for backwards-compatibility with FT 1.x anyway.            */
-  /*                                                                 */
-  FT_DECLARE_RENDERER( ft_raster5_renderer_class )
-
 
 FT_END_HEADER
 
-#endif /* __FTREND1_H__ */
+#endif /* FTREND1_H_ */
 
 
 /* END */
diff --git a/src/raster/raster.c b/src/raster/raster.c
index 1202a11..5b21dcb 100644
--- a/src/raster/raster.c
+++ b/src/raster/raster.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType monochrome rasterer module component (body only).           */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/raster/rasterrs.h b/src/raster/rasterrs.h
index ab85c00..44da7fc 100644
--- a/src/raster/rasterrs.h
+++ b/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    monochrome renderer error codes (specification only).                */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,12 +23,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __RASTERRS_H__
-#define __RASTERRS_H__
+#ifndef RASTERRS_H_
+#define RASTERRS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  Raster_Err_
@@ -36,7 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __RASTERRS_H__ */
+#endif /* RASTERRS_H_ */
 
 
 /* END */
diff --git a/src/raster/rastpic.c b/src/raster/rastpic.c
index 5e9f7cc..dcfa92e 100644
--- a/src/raster/rastpic.c
+++ b/src/raster/rastpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for raster module.   */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -59,8 +59,9 @@
     FT_Memory          memory        = library->memory;
 
 
-    /* since this function also serves raster5 renderer, */
-    /* it implements reference counting                  */
+    /* XXX: since this function also served the no longer available  */
+    /*      raster5 renderer it uses reference counting, which could */
+    /*      be removed now                                           */
     if ( pic_container->raster )
     {
       ((RasterPIC*)pic_container->raster)->ref_count++;
@@ -82,21 +83,6 @@
     return error;
   }
 
-
-  /* re-route these init and free functions to the above functions */
-  FT_Error
-  ft_raster5_renderer_class_pic_init( FT_Library  library )
-  {
-    return ft_raster1_renderer_class_pic_init( library );
-  }
-
-
-  void
-  ft_raster5_renderer_class_pic_free( FT_Library  library )
-  {
-    ft_raster1_renderer_class_pic_free( library );
-  }
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
diff --git a/src/raster/rastpic.h b/src/raster/rastpic.h
index e0ddba6..7815876 100644
--- a/src/raster/rastpic.h
+++ b/src/raster/rastpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for raster module.   */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,15 +16,15 @@
 /***************************************************************************/
 
 
-#ifndef __RASTPIC_H__
-#define __RASTPIC_H__
+#ifndef RASTPIC_H_
+#define RASTPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
 
+FT_BEGIN_HEADER
+
 #ifndef FT_CONFIG_OPTION_PIC
 
 #define FT_STANDARD_RASTER_GET  ft_standard_raster
@@ -48,22 +48,16 @@
   void
   ft_raster1_renderer_class_pic_free( FT_Library  library );
 
-  void
-  ft_raster5_renderer_class_pic_free( FT_Library  library );
-
   FT_Error
   ft_raster1_renderer_class_pic_init( FT_Library  library );
 
-  FT_Error
-  ft_raster5_renderer_class_pic_init( FT_Library  library );
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
 FT_END_HEADER
 
-#endif /* __RASTPIC_H__ */
+#endif /* RASTPIC_H_ */
 
 
 /* END */
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 9afbe5a..2815759 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    PNG Bitmap glyph support.                                            */
 /*                                                                         */
-/*  Copyright 2013, 2014 by Google, Inc.                                   */
+/*  Copyright 2013-2016 by                                                 */
+/*  Google, Inc.                                                           */
 /*  Written by Stuart Gill and Behdad Esfahbod.                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -36,11 +37,11 @@
   /* This code is freely based on cairo-png.c.  There's so many ways */
   /* to call libpng, and the way cairo does it is defacto standard.  */
 
-  static int
-  multiply_alpha( int  alpha,
-                  int  color )
+  static unsigned int
+  multiply_alpha( unsigned int  alpha,
+                  unsigned int  color )
   {
-    int  temp = ( alpha * color ) + 0x80;
+    unsigned int  temp = alpha * color + 0x80;
 
 
     return ( temp + ( temp >> 8 ) ) >> 8;
@@ -81,10 +82,10 @@
           blue  = multiply_alpha( alpha, blue  );
         }
 
-        base[0] = blue;
-        base[1] = green;
-        base[2] = red;
-        base[3] = alpha;
+        base[0] = (unsigned char)blue;
+        base[1] = (unsigned char)green;
+        base[2] = (unsigned char)red;
+        base[3] = (unsigned char)alpha;
       }
     }
   }
@@ -109,9 +110,9 @@
       unsigned int    blue  = base[2];
 
 
-      base[0] = blue;
-      base[1] = green;
-      base[2] = red;
+      base[0] = (unsigned char)blue;
+      base[1] = (unsigned char)green;
+      base[2] = (unsigned char)red;
       base[3] = 0xFF;
     }
   }
@@ -205,11 +206,11 @@
       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   ) )
+    if ( !populate_map_and_metrics                            &&
+         ( (FT_UInt)x_offset + metrics->width  > map->width ||
+           (FT_UInt)y_offset + metrics->height > map->rows  ||
+           pix_bits != 32                                   ||
+           map->pixel_mode != FT_PIXEL_MODE_BGRA            ) )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -257,19 +258,27 @@
 
     if ( populate_map_and_metrics )
     {
-      FT_Long  size;
+      FT_ULong  size;
 
 
-      metrics->width  = (FT_Int)imgWidth;
-      metrics->height = (FT_Int)imgHeight;
+      metrics->width  = (FT_UShort)imgWidth;
+      metrics->height = (FT_UShort)imgHeight;
 
       map->width      = metrics->width;
       map->rows       = metrics->height;
       map->pixel_mode = FT_PIXEL_MODE_BGRA;
-      map->pitch      = map->width * 4;
+      map->pitch      = (int)( map->width * 4 );
       map->num_grays  = 256;
 
-      size = map->rows * map->pitch;
+      /* reject too large bitmaps similarly to the rasterizer */
+      if ( map->rows > 0x7FFF || map->width > 0x7FFF )
+      {
+        error = FT_THROW( Array_Too_Large );
+        goto DestroyExit;
+      }
+
+      /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
+      size = map->rows * (FT_ULong)map->pitch;
 
       error = ft_glyphslot_alloc_bitmap( slot, size );
       if ( error )
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
index dc9ecaf..ff05871 100644
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    PNG Bitmap glyph support.                                            */
 /*                                                                         */
-/*  Copyright 2013 by Google, Inc.                                         */
+/*  Copyright 2013-2016 by                                                 */
+/*  Google, Inc.                                                           */
 /*  Written by Stuart Gill and Behdad Esfahbod.                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __PNGSHIM_H__
-#define __PNGSHIM_H__
+#ifndef PNGSHIM_H_
+#define PNGSHIM_H_
 
 
 #include <ft2build.h>
@@ -43,7 +44,7 @@
 
 FT_END_HEADER
 
-#endif /* __PNGSHIM_H__ */
+#endif /* PNGSHIM_H_ */
 
 
 /* END */
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index e4fcda5..2233269 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (body).                             */
 /*                                                                         */
-/*  Copyright 1996-2007, 2009-2014 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -75,36 +75,36 @@
 
     switch ( tag )
     {
-    case ft_sfnt_head:
+    case FT_SFNT_HEAD:
       table = &face->header;
       break;
 
-    case ft_sfnt_hhea:
+    case FT_SFNT_HHEA:
       table = &face->horizontal;
       break;
 
-    case ft_sfnt_vhea:
-      table = face->vertical_info ? &face->vertical : 0;
+    case FT_SFNT_VHEA:
+      table = face->vertical_info ? &face->vertical : NULL;
       break;
 
-    case ft_sfnt_os2:
-      table = face->os2.version == 0xFFFFU ? 0 : &face->os2;
+    case FT_SFNT_OS2:
+      table = face->os2.version == 0xFFFFU ? NULL : &face->os2;
       break;
 
-    case ft_sfnt_post:
+    case FT_SFNT_POST:
       table = &face->postscript;
       break;
 
-    case ft_sfnt_maxp:
+    case FT_SFNT_MAXP:
       table = &face->max_profile;
       break;
 
-    case ft_sfnt_pclt:
-      table = face->pclt.Version ? &face->pclt : 0;
+    case FT_SFNT_PCLT:
+      table = face->pclt.Version ? &face->pclt : NULL;
       break;
 
     default:
-      table = 0;
+      table = NULL;
     }
 
     return table;
@@ -139,9 +139,9 @@
 
   FT_DEFINE_SERVICE_SFNT_TABLEREC(
     sfnt_service_sfnt_table,
-    (FT_SFNT_TableLoadFunc)tt_face_load_any,
-    (FT_SFNT_TableGetFunc) get_sfnt_table,
-    (FT_SFNT_TableInfoFunc)sfnt_table_info )
+    (FT_SFNT_TableLoadFunc)tt_face_load_any,     /* load_table */
+    (FT_SFNT_TableGetFunc) get_sfnt_table,       /* get_table  */
+    (FT_SFNT_TableInfoFunc)sfnt_table_info )     /* table_info */
 
 
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -205,8 +205,8 @@
 
   FT_DEFINE_SERVICE_GLYPHDICTREC(
     sfnt_service_glyph_dict,
-    (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,
-    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
+    (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,    /* get_name   */
+    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )   /* name_index */
 
 
 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -266,7 +266,7 @@
       {
         FT_Stream   stream = face->name_table.stream;
         FT_String*  r      = (FT_String*)result;
-        FT_Byte*    p;
+        FT_Char*    p;
 
 
         if ( FT_STREAM_SEEK( name->stringOffset ) ||
@@ -280,11 +280,11 @@
           goto Exit;
         }
 
-        p = (FT_Byte*)stream->cursor;
+        p = (FT_Char*)stream->cursor;
 
         for ( ; len > 0; len--, p += 2 )
         {
-          if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
+          if ( p[0] == 0 && p[1] >= 32 )
             *r++ = p[1];
         }
         *r = '\0';
@@ -330,7 +330,7 @@
 
   FT_DEFINE_SERVICE_PSFONTNAMEREC(
     sfnt_service_ps_name,
-    (FT_PsName_GetFunc)sfnt_get_ps_name )
+    (FT_PsName_GetFunc)sfnt_get_ps_name )     /* get_ps_font_name */
 
 
   /*
@@ -338,7 +338,7 @@
    */
   FT_DEFINE_SERVICE_TTCMAPSREC(
     tt_service_get_cmap_info,
-    (TT_CMap_Info_GetFunc)tt_get_cmap_info )
+    (TT_CMap_Info_GetFunc)tt_get_cmap_info )  /* get_cmap_info */
 
 
 #ifdef TT_CONFIG_OPTION_BDF
@@ -381,8 +381,8 @@
 
   FT_DEFINE_SERVICE_BDFRec(
     sfnt_service_bdf,
-    (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
-    (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
+    (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,     /* get_charset_id */
+    (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )  /* get_property   */
 
 
 #endif /* TT_CONFIG_OPTION_BDF */
@@ -427,7 +427,7 @@
   sfnt_get_interface( FT_Module    module,
                       const char*  module_interface )
   {
-    /* SFNT_SERVICES_GET derefers `library' in PIC mode */
+    /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     FT_Library  library;
 
@@ -459,53 +459,62 @@
 
   FT_DEFINE_SFNT_INTERFACE(
     sfnt_interface,
-    tt_face_goto_table,
+    tt_face_goto_table,     /* TT_Loader_GotoTableFunc goto_table      */
 
-    sfnt_init_face,
-    sfnt_load_face,
-    sfnt_done_face,
-    sfnt_get_interface,
+    sfnt_init_face,         /* TT_Init_Face_Func       init_face       */
+    sfnt_load_face,         /* TT_Load_Face_Func       load_face       */
+    sfnt_done_face,         /* TT_Done_Face_Func       done_face       */
+    sfnt_get_interface,     /* FT_Module_Requester     get_interface   */
 
-    tt_face_load_any,
+    tt_face_load_any,       /* TT_Load_Any_Func        load_any        */
 
-    tt_face_load_head,
-    tt_face_load_hhea,
-    tt_face_load_cmap,
-    tt_face_load_maxp,
-    tt_face_load_os2,
-    tt_face_load_post,
+    tt_face_load_head,      /* TT_Load_Table_Func      load_head       */
+    tt_face_load_hhea,      /* TT_Load_Metrics_Func    load_hhea       */
+    tt_face_load_cmap,      /* TT_Load_Table_Func      load_cmap       */
+    tt_face_load_maxp,      /* TT_Load_Table_Func      load_maxp       */
+    tt_face_load_os2,       /* TT_Load_Table_Func      load_os2        */
+    tt_face_load_post,      /* TT_Load_Table_Func      load_post       */
 
-    tt_face_load_name,
-    tt_face_free_name,
+    tt_face_load_name,      /* TT_Load_Table_Func      load_name       */
+    tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
 
-    tt_face_load_kern,
-    tt_face_load_gasp,
-    tt_face_load_pclt,
+    tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
+    tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
+    tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
 
     /* see `ttload.h' */
     PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
-
+                            /* TT_Load_Table_Func      load_bhed       */
     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
+                            /* TT_Load_SBit_Image_Func load_sbit_image */
 
     /* see `ttpost.h' */
     PUT_PS_NAMES( tt_face_get_ps_name   ),
+                            /* TT_Get_PS_Name_Func     get_psname      */
     PUT_PS_NAMES( tt_face_free_ps_names ),
+                            /* TT_Free_Table_Func      free_psnames    */
 
     /* since version 2.1.8 */
-    tt_face_get_kerning,
+    tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
 
     /* since version 2.2 */
-    tt_face_load_font_dir,
-    tt_face_load_hmtx,
+    tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
+    tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
 
     /* see `ttsbit.h' and `sfnt.h' */
     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
+                            /* TT_Load_Table_Func      load_eblc       */
     PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
+                            /* TT_Free_Table_Func      free_eblc       */
 
     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
+                            /* TT_Set_SBit_Strike_Func set_sbit_strike */
     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
+                    /* TT_Load_Strike_Metrics_Func load_strike_metrics */
 
-    tt_face_get_metrics
+    tt_face_get_metrics,    /* TT_Get_Metrics_Func     get_metrics     */
+
+    tt_face_get_name        /* TT_Get_Name_Func        get_name        */
   )
 
 
diff --git a/src/sfnt/sfdriver.h b/src/sfnt/sfdriver.h
index 5de25d5..2694488 100644
--- a/src/sfnt/sfdriver.h
+++ b/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SFDRIVER_H__
-#define __SFDRIVER_H__
+#ifndef SFDRIVER_H_
+#define SFDRIVER_H_
 
 
 #include <ft2build.h>
@@ -32,7 +32,7 @@
 
 FT_END_HEADER
 
-#endif /* __SFDRIVER_H__ */
+#endif /* SFDRIVER_H_ */
 
 
 /* END */
diff --git a/src/sfnt/sferrors.h b/src/sfnt/sferrors.h
index e981e1d..c2f9fdf 100644
--- a/src/sfnt/sferrors.h
+++ b/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT error codes (specification only).                               */
 /*                                                                         */
-/*  Copyright 2001, 2004, 2012, 2013 by                                    */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,12 +22,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __SFERRORS_H__
-#define __SFERRORS_H__
+#ifndef SFERRORS_H_
+#define SFERRORS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  SFNT_Err_
@@ -35,6 +35,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __SFERRORS_H__ */
+#endif /* SFERRORS_H_ */
+
 
 /* END */
diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c
index d62ed4e..952d6d4 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Single object library component.                                     */
 /*                                                                         */
-/*  Copyright 1996-2006, 2013 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/sfnt/sfntpic.c b/src/sfnt/sfntpic.c
index b3fb24b..1f596c0 100644
--- a/src/sfnt/sfntpic.c
+++ b/src/sfnt/sfntpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for sfnt module.     */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/sfnt/sfntpic.h b/src/sfnt/sfntpic.h
index b09a914..5ce96d3 100644
--- a/src/sfnt/sfntpic.h
+++ b/src/sfnt/sfntpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for sfnt module.     */
 /*                                                                         */
-/*  Copyright 2009, 2012 by                                                */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,12 +16,10 @@
 /***************************************************************************/
 
 
-#ifndef __SFNTPIC_H__
-#define __SFNTPIC_H__
+#ifndef SFNTPIC_H_
+#define SFNTPIC_H_
 
 
-FT_BEGIN_HEADER
-
 #include FT_INTERNAL_PIC_H
 
 
@@ -31,7 +29,6 @@
 #define SFNT_SERVICE_GLYPH_DICT_GET  sfnt_service_glyph_dict
 #define SFNT_SERVICE_PS_NAME_GET     sfnt_service_ps_name
 #define TT_SERVICE_CMAP_INFO_GET     tt_service_get_cmap_info
-#define SFNT_SERVICES_GET            sfnt_services
 #define TT_CMAP_CLASSES_GET          tt_cmap_classes
 #define SFNT_SERVICE_SFNT_TABLE_GET  sfnt_service_sfnt_table
 #define SFNT_SERVICE_BDF_GET         sfnt_service_bdf
@@ -56,6 +53,8 @@
 #include "ttcmap.h"
 
 
+FT_BEGIN_HEADER
+
   typedef struct  sfntModulePIC_
   {
     FT_ServiceDescRec*        sfnt_services;
@@ -83,8 +82,6 @@
           ( GET_PIC( library )->sfnt_service_ps_name )
 #define TT_SERVICE_CMAP_INFO_GET                           \
           ( GET_PIC( library )->tt_service_get_cmap_info )
-#define SFNT_SERVICES_GET                       \
-          ( GET_PIC( library )->sfnt_services )
 #define TT_CMAP_CLASSES_GET                       \
           ( GET_PIC( library )->tt_cmap_classes )
 #define SFNT_SERVICE_SFNT_TABLE_GET                       \
@@ -102,13 +99,14 @@
   FT_Error
   sfnt_module_class_pic_init( FT_Library  library );
 
+
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
   /* */
 
-FT_END_HEADER
-
-#endif /* __SFNTPIC_H__ */
+#endif /* SFNTPIC_H_ */
 
 
 /* END */
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 44aa467..ceeae20 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (base).                                       */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010-2014 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -120,27 +120,9 @@
                                                    FT_Memory     memory );
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_face_get_name                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Returns a given ENGLISH name record in ASCII.                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face   :: A handle to the source face object.                      */
-  /*                                                                       */
-  /*    nameid :: The name id of the name record to return.                */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    name   :: The address of a string pointer.  NULL if no name is     */
-  /*              present.                                                 */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
+  /* documentation is in sfnt.h */
+
+  FT_LOCAL_DEF( FT_Error )
   tt_face_get_name( TT_Face      face,
                     FT_UShort    nameid,
                     FT_String**  name )
@@ -376,8 +358,8 @@
     FT_FREE( stream->base );
 
     stream->size  = 0;
-    stream->base  = 0;
-    stream->close = 0;
+    stream->base  = NULL;
+    stream->close = NULL;
   }
 
 
@@ -469,10 +451,14 @@
                                      woff.metaOrigLength != 0 ) ) ||
          ( woff.metaLength != 0 && woff.metaOrigLength == 0 )     ||
          ( woff.privOffset == 0 && woff.privLength != 0 )         )
+    {
+      FT_ERROR(( "woff_font_open: invalid WOFF header\n" ));
       return FT_THROW( Invalid_Table );
+    }
 
-    if ( FT_ALLOC( sfnt, woff.totalSfntSize ) ||
-         FT_NEW( sfnt_stream )                )
+    /* Don't trust `totalSfntSize' before thorough checks. */
+    if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
+         FT_NEW( sfnt_stream )                         )
       goto Exit;
 
     sfnt_header = sfnt;
@@ -539,6 +525,8 @@
       if ( table->Tag <= old_tag )
       {
         FT_FRAME_EXIT();
+
+        FT_ERROR(( "woff_font_open: table tags are not sorted\n" ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
       }
@@ -567,10 +555,13 @@
 
 
       if ( table->Offset != woff_offset                         ||
-           table->Offset + table->CompLength > woff.length      ||
-           sfnt_offset + table->OrigLength > woff.totalSfntSize ||
+           table->CompLength > woff.length                      ||
+           table->Offset > woff.length - table->CompLength      ||
+           table->OrigLength > woff.totalSfntSize               ||
+           sfnt_offset > woff.totalSfntSize - table->OrigLength ||
            table->CompLength > table->OrigLength                )
       {
+        FT_ERROR(( "woff_font_open: invalid table offsets\n" ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
       }
@@ -578,8 +569,8 @@
       table->OrigOffset = sfnt_offset;
 
       /* The offsets must be multiples of 4. */
-      woff_offset += ( table->CompLength + 3 ) & ~3;
-      sfnt_offset += ( table->OrigLength + 3 ) & ~3;
+      woff_offset += ( table->CompLength + 3 ) & ~3U;
+      sfnt_offset += ( table->OrigLength + 3 ) & ~3U;
     }
 
     /*
@@ -596,6 +587,8 @@
       if ( woff.metaOffset != woff_offset                  ||
            woff.metaOffset + woff.metaLength > woff.length )
       {
+        FT_ERROR(( "woff_font_open:"
+                   " invalid `metadata' offset or length\n" ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
       }
@@ -607,11 +600,12 @@
     if ( woff.privOffset )
     {
       /* ... if it isn't the last block. */
-      woff_offset = ( woff_offset + 3 ) & ~3;
+      woff_offset = ( woff_offset + 3 ) & ~3U;
 
       if ( woff.privOffset != woff_offset                  ||
            woff.privOffset + woff.privLength > woff.length )
       {
+        FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
       }
@@ -623,10 +617,19 @@
     if ( sfnt_offset != woff.totalSfntSize ||
          woff_offset != woff.length        )
     {
+      FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" ));
       error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
+    /* Now use `totalSfntSize'. */
+    if ( FT_REALLOC( sfnt,
+                     12 + woff.num_tables * 16UL,
+                     woff.totalSfntSize ) )
+      goto Exit;
+
+    sfnt_header = sfnt + 12;
+
     /* Write the tables. */
 
     for ( nn = 0; nn < woff.num_tables; nn++ )
@@ -667,6 +670,7 @@
           goto Exit;
         if ( output_len != table->OrigLength )
         {
+          FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
         }
@@ -837,13 +841,14 @@
   FT_LOCAL_DEF( FT_Error )
   sfnt_init_face( FT_Stream      stream,
                   TT_Face        face,
-                  FT_Int         face_index,
+                  FT_Int         face_instance_index,
                   FT_Int         num_params,
                   FT_Parameter*  params )
   {
-    FT_Error        error;
-    FT_Library      library = face->root.driver->root.library;
-    SFNT_Service    sfnt;
+    FT_Error      error;
+    FT_Library    library = face->root.driver->root.library;
+    SFNT_Service  sfnt;
+    FT_Int        face_index;
 
 
     /* for now, parameters are unused */
@@ -876,24 +881,103 @@
     /* Stream may have changed in sfnt_open_font. */
     stream = face->root.stream;
 
-    FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
+    FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index ));
 
-    if ( face_index < 0 )
-      face_index = 0;
+    face_index = FT_ABS( face_instance_index ) & 0xFFFF;
 
     if ( face_index >= face->ttc_header.count )
-      return FT_THROW( Invalid_Argument );
+    {
+      if ( face_instance_index >= 0 )
+        return FT_THROW( Invalid_Argument );
+      else
+        face_index = 0;
+    }
 
     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
       return error;
 
-    /* check that we have a valid TrueType file */
+    /* check whether we have a valid TrueType file */
     error = sfnt->load_font_dir( face, stream );
     if ( error )
       return error;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    {
+      FT_ULong  fvar_len;
+
+      FT_ULong  version;
+      FT_ULong  offset;
+
+      FT_UShort  num_axes;
+      FT_UShort  axis_size;
+      FT_UShort  num_instances;
+      FT_UShort  instance_size;
+
+      FT_Int  instance_index;
+
+
+      instance_index = FT_ABS( face_instance_index ) >> 16;
+
+      /* test whether current face is a GX font with named instances */
+      if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
+           fvar_len < 20                                          ||
+           FT_READ_ULONG( version )                               ||
+           FT_READ_USHORT( offset )                               ||
+           FT_STREAM_SKIP( 2 )                                    ||
+           FT_READ_USHORT( num_axes )                             ||
+           FT_READ_USHORT( axis_size )                            ||
+           FT_READ_USHORT( num_instances )                        ||
+           FT_READ_USHORT( instance_size )                        )
+      {
+        version       = 0;
+        offset        = 0;
+        num_axes      = 0;
+        axis_size     = 0;
+        num_instances = 0;
+        instance_size = 0;
+      }
+
+      /* check that the data is bound by the table length; */
+      /* based on similar code in function `TT_Get_MM_Var' */
+      if ( version != 0x00010000UL                    ||
+           axis_size != 20                            ||
+           num_axes > 0x3FFE                          ||
+           instance_size != 4 + 4 * num_axes          ||
+           num_instances > 0x7EFF                     ||
+           offset                          +
+             axis_size * num_axes          +
+             instance_size * num_instances > fvar_len )
+        num_instances = 0;
+
+      /* we don't support Multiple Master CFFs yet */
+      if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
+        num_instances = 0;
+
+      /* we support at most 2^15 - 1 instances */
+      if ( num_instances >= ( 1U << 15 ) - 1 )
+      {
+        if ( face_instance_index >= 0 )
+          return FT_THROW( Invalid_Argument );
+        else
+          num_instances = 0;
+      }
+
+      /* instance indices in `face_instance_index' start with index 1, */
+      /* thus `>' and not `>='                                         */
+      if ( instance_index > num_instances )
+      {
+        if ( face_instance_index >= 0 )
+          return FT_THROW( Invalid_Argument );
+        else
+          num_instances = 0;
+      }
+
+      face->root.style_flags = (FT_Long)num_instances << 16;
+    }
+#endif
+
     face->root.num_faces  = face->ttc_header.count;
-    face->root.face_index = face_index;
+    face->root.face_index = face_instance_index;
 
     return error;
   }
@@ -944,7 +1028,7 @@
   FT_LOCAL_DEF( FT_Error )
   sfnt_load_face( FT_Stream      stream,
                   TT_Face        face,
-                  FT_Int         face_index,
+                  FT_Int         face_instance_index,
                   FT_Int         num_params,
                   FT_Parameter*  params )
   {
@@ -960,7 +1044,7 @@
 
     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 
-    FT_UNUSED( face_index );
+    FT_UNUSED( face_instance_index );
 
 
     /* Check parameters */
@@ -1016,7 +1100,6 @@
     if ( is_apple_sbix )
       has_outline = FALSE;
 
-
     /* if this font doesn't contain outlines, we try to load */
     /* a `bhed' table                                        */
     if ( !has_outline && sfnt->load_bhed )
@@ -1283,7 +1366,7 @@
           flags |= FT_STYLE_FLAG_ITALIC;
       }
 
-      root->style_flags = flags;
+      root->style_flags |= flags;
 
       /*********************************************************************/
       /*                                                                   */
@@ -1328,7 +1411,7 @@
        *  depths in the FT_Bitmap_Size record.  This is a design error.
        */
       {
-        FT_UInt  i, count;
+        FT_UInt  count;
 
 
         count = face->sbit_num_strikes;
@@ -1340,6 +1423,9 @@
           FT_Short         avgwidth = face->os2.xAvgCharWidth;
           FT_Size_Metrics  metrics;
 
+          FT_UInt*  sbit_strike_map = NULL;
+          FT_UInt   strike_idx, bsize_idx;
+
 
           if ( em_size == 0 || face->os2.version == 0xFFFFU )
           {
@@ -1347,31 +1433,50 @@
             em_size = 1;
           }
 
-          if ( FT_NEW_ARRAY( root->available_sizes, count ) )
+          /* to avoid invalid strike data in the `available_sizes' field */
+          /* of `FT_Face', we map `available_sizes' indices to strike    */
+          /* indices                                                     */
+          if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
+               FT_NEW_ARRAY( sbit_strike_map, count ) )
             goto Exit;
 
-          for ( i = 0; i < count; i++ )
+          bsize_idx = 0;
+          for ( strike_idx = 0; strike_idx < count; strike_idx++ )
           {
-            FT_Bitmap_Size*  bsize = root->available_sizes + i;
+            FT_Bitmap_Size*  bsize = root->available_sizes + bsize_idx;
 
 
-            error = sfnt->load_strike_metrics( face, i, &metrics );
+            error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
             if ( error )
-              goto Exit;
+              continue;
 
             bsize->height = (FT_Short)( metrics.height >> 6 );
-            bsize->width = (FT_Short)(
-                ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
+            bsize->width  = (FT_Short)(
+              ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
 
             bsize->x_ppem = metrics.x_ppem << 6;
             bsize->y_ppem = metrics.y_ppem << 6;
 
             /* assume 72dpi */
             bsize->size   = metrics.y_ppem << 6;
+
+            /* only use strikes with valid PPEM values */
+            if ( bsize->x_ppem && bsize->y_ppem )
+              sbit_strike_map[bsize_idx++] = strike_idx;
           }
 
-          root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
-          root->num_fixed_sizes = (FT_Int)count;
+          /* reduce array size to the actually used elements */
+          (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx );
+
+          /* from now on, all strike indices are mapped */
+          /* using `sbit_strike_map'                    */
+          if ( bsize_idx )
+          {
+            face->sbit_strike_map = sbit_strike_map;
+
+            root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
+            root->num_fixed_sizes = (FT_Int)bsize_idx;
+          }
         }
       }
 
@@ -1430,8 +1535,8 @@
         root->ascender  = face->horizontal.Ascender;
         root->descender = face->horizontal.Descender;
 
-        root->height = (FT_Short)( root->ascender - root->descender +
-                                   face->horizontal.Line_Gap );
+        root->height = root->ascender - root->descender +
+                       face->horizontal.Line_Gap;
 
         if ( !( root->ascender || root->descender ) )
         {
@@ -1442,23 +1547,24 @@
               root->ascender  = face->os2.sTypoAscender;
               root->descender = face->os2.sTypoDescender;
 
-              root->height = (FT_Short)( root->ascender - root->descender +
-                                         face->os2.sTypoLineGap );
+              root->height = root->ascender - root->descender +
+                             face->os2.sTypoLineGap;
             }
             else
             {
               root->ascender  =  (FT_Short)face->os2.usWinAscent;
               root->descender = -(FT_Short)face->os2.usWinDescent;
 
-              root->height = (FT_UShort)( root->ascender - root->descender );
+              root->height = root->ascender - root->descender;
             }
           }
         }
 
-        root->max_advance_width  = face->horizontal.advance_Width_Max;
-        root->max_advance_height = (FT_Short)( face->vertical_info
-                                     ? face->vertical.advance_Height_Max
-                                     : root->height );
+        root->max_advance_width  =
+          (FT_Short)face->horizontal.advance_Width_Max;
+        root->max_advance_height =
+          (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
+                                          : root->height );
 
         /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
         /* Adjust underline position from top edge to centre of     */
@@ -1564,11 +1670,12 @@
 
     /* freeing sbit size table */
     FT_FREE( face->root.available_sizes );
+    FT_FREE( face->sbit_strike_map );
     face->root.num_fixed_sizes = 0;
 
     FT_FREE( face->postscript_name );
 
-    face->sfnt = 0;
+    face->sfnt = NULL;
   }
 
 
diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h
index 6241c93..60b5698 100644
--- a/src/sfnt/sfobjs.h
+++ b/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (specification).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SFOBJS_H__
-#define __SFOBJS_H__
+#ifndef SFOBJS_H_
+#define SFOBJS_H_
 
 
 #include <ft2build.h>
@@ -31,24 +31,29 @@
   FT_LOCAL( FT_Error )
   sfnt_init_face( FT_Stream      stream,
                   TT_Face        face,
-                  FT_Int         face_index,
+                  FT_Int         face_instance_index,
                   FT_Int         num_params,
                   FT_Parameter*  params );
 
   FT_LOCAL( FT_Error )
   sfnt_load_face( FT_Stream      stream,
                   TT_Face        face,
-                  FT_Int         face_index,
+                  FT_Int         face_instance_index,
                   FT_Int         num_params,
                   FT_Parameter*  params );
 
   FT_LOCAL( void )
   sfnt_done_face( TT_Face  face );
 
+  FT_LOCAL( FT_Error )
+  tt_face_get_name( TT_Face      face,
+                    FT_UShort    nameid,
+                    FT_String**  name );
+
 
 FT_END_HEADER
 
-#endif /* __SFDRIVER_H__ */
+#endif /* SFDRIVER_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c
index 9401dae..f891691 100644
--- a/src/sfnt/ttbdf.c
+++ b/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded BDF properties (body).                */
 /*                                                                         */
-/*  Copyright 2005, 2006, 2010, 2013 by                                    */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/sfnt/ttbdf.h b/src/sfnt/ttbdf.h
index 48a10d6..ae521c6 100644
--- a/src/sfnt/ttbdf.h
+++ b/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded BDF properties (specification).       */
 /*                                                                         */
-/*  Copyright 2005 by                                                      */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTBDF_H__
-#define __TTBDF_H__
+#ifndef TTBDF_H_
+#define TTBDF_H_
 
 
 #include <ft2build.h>
@@ -40,7 +40,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTBDF_H__ */
+#endif /* TTBDF_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index f9acf5d..cd7467d 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (body).              */
 /*                                                                         */
-/*  Copyright 2002-2010, 2012-2014 by                                      */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -51,6 +51,13 @@
 #define TT_NEXT_ULONG   FT_NEXT_ULONG
 
 
+  /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
+  /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
+  /* again in this case).  To mark character code return values as invalid */
+  /* it is sufficient to set the corresponding glyph index return value to */
+  /* zero.                                                                 */
+
+
   FT_CALLBACK_DEF( FT_Error )
   tt_cmap_init( TT_CMap   cmap,
                 FT_Byte*  table )
@@ -199,7 +206,7 @@
   /*****                          FORMAT 2                             *****/
   /*****                                                               *****/
   /***** This is used for certain CJK encodings that encode text in a  *****/
-  /***** mixed 8/16 bits encoding along the following lines:           *****/
+  /***** mixed 8/16 bits encoding along the following lines.           *****/
   /*****                                                               *****/
   /***** * Certain byte values correspond to an 8-bit character code   *****/
   /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
@@ -209,19 +216,19 @@
   /*****   second byte of a 2-byte character).                         *****/
   /*****                                                               *****/
   /***** The following charmap lookup and iteration functions all      *****/
-  /***** assume that the value "charcode" correspond to following:     *****/
+  /***** assume that the value `charcode' fulfills the following.      *****/
   /*****                                                               *****/
-  /*****   - For one byte characters, "charcode" is simply the         *****/
+  /*****   - For one byte characters, `charcode' is simply the         *****/
   /*****     character code.                                           *****/
   /*****                                                               *****/
-  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
-  /*****     character code in big endian format.  More exactly:       *****/
+  /*****   - For two byte characters, `charcode' is the 2-byte         *****/
+  /*****     character code in big endian format.  More precisely:     *****/
   /*****                                                               *****/
   /*****       (charcode >> 8)    is the first byte value              *****/
   /*****       (charcode & 0xFF)  is the second byte value             *****/
   /*****                                                               *****/
-  /***** Note that not all values of "charcode" are valid according    *****/
-  /***** to these rules, and the function moderately check the         *****/
+  /***** Note that not all values of `charcode' are valid according    *****/
+  /***** to these rules, and the function moderately checks the        *****/
   /***** arguments.                                                    *****/
   /*****                                                               *****/
   /*************************************************************************/
@@ -249,7 +256,7 @@
   /* table, i.e., it is the corresponding sub-header index multiplied      */
   /* by 8.                                                                 */
   /*                                                                       */
-  /* Each sub-header has the following format:                             */
+  /* Each sub-header has the following format.                             */
   /*                                                                       */
   /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
   /*                                                                       */
@@ -264,11 +271,11 @@
   /* according to the specification.                                       */
   /*                                                                       */
   /* If a character code is contained within a given sub-header, then      */
-  /* mapping it to a glyph index is done as follows:                       */
+  /* mapping it to a glyph index is done as follows.                       */
   /*                                                                       */
   /* * The value of `offset' is read.  This is a _byte_ distance from the  */
   /*   location of the `offset' field itself into a slice of the           */
-  /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[] too).   */
+  /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[], too).  */
   /*                                                                       */
   /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
   /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
@@ -326,7 +333,7 @@
     FT_ASSERT( p == table + 518 );
 
     subs      = p;
-    glyph_ids = subs + (max_subs + 1) * 8;
+    glyph_ids = subs + ( max_subs + 1 ) * 8;
     if ( glyph_ids > valid->limit )
       FT_INVALID_TOO_SHORT;
 
@@ -360,7 +367,7 @@
 
 
         ids = p - 2 + offset;
-        if ( ids < glyph_ids || ids + code_count*2 > table + length )
+        if ( ids < glyph_ids || ids + code_count * 2 > table + length )
           FT_INVALID_OFFSET;
 
         /* check glyph IDs */
@@ -375,7 +382,7 @@
             idx = TT_NEXT_USHORT( p );
             if ( idx != 0 )
             {
-              idx = ( idx + delta ) & 0xFFFFU;
+              idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
               if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
                 FT_INVALID_GLYPH_ID;
             }
@@ -436,6 +443,7 @@
       }
       result = sub;
     }
+
   Exit:
     return result;
   }
@@ -472,9 +480,10 @@
         idx = TT_PEEK_USHORT( p );
 
         if ( idx != 0 )
-          result = (FT_UInt)( idx + delta ) & 0xFFFFU;
+          result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
       }
     }
+
     return result;
   }
 
@@ -524,7 +533,7 @@
 
           if ( idx != 0 )
           {
-            gindex = ( idx + delta ) & 0xFFFFU;
+            gindex = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
             if ( gindex != 0 )
             {
               result = charcode;
@@ -754,6 +763,9 @@
   static void
   tt_cmap4_next( TT_CMap4  cmap )
   {
+    TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
+    FT_Byte*  limit = face->cmap_table + face->cmap_size;
+
     FT_UInt  charcode;
 
 
@@ -765,7 +777,7 @@
     if ( charcode < cmap->cur_start )
       charcode = cmap->cur_start;
 
-    for ( ;; )
+    for (;;)
     {
       FT_Byte*  values = cmap->cur_values;
       FT_UInt   end    = cmap->cur_end;
@@ -779,15 +791,19 @@
           FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
 
 
+          /* if p > limit, the whole segment is invalid */
+          if ( p > limit )
+            goto Next_Segment;
+
           do
           {
             FT_UInt  gindex = FT_NEXT_USHORT( p );
 
 
-            if ( gindex != 0 )
+            if ( gindex )
             {
-              gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
-              if ( gindex != 0 )
+              gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+              if ( gindex )
               {
                 cmap->cur_charcode = charcode;
                 cmap->cur_gindex   = gindex;
@@ -800,10 +816,29 @@
         {
           do
           {
-            FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
+            FT_UInt  gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
 
 
-            if ( gindex != 0 )
+            if ( gindex >= (FT_UInt)face->root.num_glyphs )
+            {
+              /* we have an invalid glyph index; if there is an overflow, */
+              /* we can adjust `charcode', otherwise the whole segment is */
+              /* invalid                                                  */
+              gindex = 0;
+
+              if ( (FT_Int)charcode + delta < 0 &&
+                   (FT_Int)end + delta >= 0     )
+                charcode = (FT_UInt)( -delta );
+
+              else if ( (FT_Int)charcode + delta < 0x10000L &&
+                        (FT_Int)end + delta >= 0x10000L     )
+                charcode = (FT_UInt)( 0x10000L - delta );
+
+              else
+                goto Next_Segment;
+            }
+
+            if ( gindex )
             {
               cmap->cur_charcode = charcode;
               cmap->cur_gindex   = gindex;
@@ -813,6 +848,7 @@
         }
       }
 
+    Next_Segment:
       /* we need to find another range */
       if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
         break;
@@ -845,9 +881,6 @@
     p      = table + 2;           /* skip format */
     length = TT_NEXT_USHORT( p );
 
-    if ( length < 16 )
-      FT_INVALID_TOO_SHORT;
-
     /* in certain fonts, the `length' field is invalid and goes */
     /* out of bound.  We try to correct this here...            */
     if ( table + length > valid->limit )
@@ -858,6 +891,9 @@
       length = (FT_UInt)( valid->limit - table );
     }
 
+    if ( length < 16 )
+      FT_INVALID_TOO_SHORT;
+
     p        = table + 6;
     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
 
@@ -973,7 +1009,7 @@
           /* segment if it contains only a single character.     */
           /*                                                     */
           /* We thus omit the test here, delaying it to the      */
-          /* routines which actually access the cmap.            */
+          /* routines that actually access the cmap.             */
           else if ( n != num_segs - 1                       ||
                     !( start == 0xFFFFU && end == 0xFFFFU ) )
           {
@@ -993,7 +1029,7 @@
               idx = FT_NEXT_USHORT( p );
               if ( idx != 0 )
               {
-                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
+                idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
 
                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
                   FT_INVALID_GLYPH_ID;
@@ -1026,12 +1062,17 @@
                             FT_UInt32*  pcharcode,
                             FT_Bool     next )
   {
+    TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
+    FT_Byte*  limit = face->cmap_table + face->cmap_size;
+
+
     FT_UInt    num_segs2, start, end, offset;
     FT_Int     delta;
     FT_UInt    i, num_segs;
     FT_UInt32  charcode = *pcharcode;
     FT_UInt    gindex   = 0;
     FT_Byte*   p;
+    FT_Byte*   q;
 
 
     p = cmap->data + 6;
@@ -1045,65 +1086,106 @@
     if ( next )
       charcode++;
 
+    if ( charcode > 0xFFFFU )
+      return 0;
+
     /* linear search */
-    for ( ; charcode <= 0xFFFFU; charcode++ )
+    p = cmap->data + 14;               /* ends table   */
+    q = cmap->data + 16 + num_segs2;   /* starts table */
+
+    for ( i = 0; i < num_segs; i++ )
     {
-      FT_Byte*  q;
+      end   = TT_NEXT_USHORT( p );
+      start = TT_NEXT_USHORT( q );
 
-
-      p = cmap->data + 14;               /* ends table   */
-      q = cmap->data + 16 + num_segs2;   /* starts table */
-
-      for ( i = 0; i < num_segs; i++ )
+      if ( charcode < start )
       {
-        end   = TT_NEXT_USHORT( p );
-        start = TT_NEXT_USHORT( q );
-
-        if ( charcode >= start && charcode <= end )
-        {
-          p       = q - 2 + num_segs2;
-          delta   = TT_PEEK_SHORT( p );
-          p      += num_segs2;
-          offset  = TT_PEEK_USHORT( p );
-
-          /* some fonts have an incorrect last segment; */
-          /* we have to catch it                        */
-          if ( i >= num_segs - 1                  &&
-               start == 0xFFFFU && end == 0xFFFFU )
-          {
-            TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
-            FT_Byte*  limit = face->cmap_table + face->cmap_size;
-
-
-            if ( offset && p + offset + 2 > limit )
-            {
-              delta  = 1;
-              offset = 0;
-            }
-          }
-
-          if ( offset == 0xFFFFU )
-            continue;
-
-          if ( offset )
-          {
-            p += offset + ( charcode - start ) * 2;
-            gindex = TT_PEEK_USHORT( p );
-            if ( gindex != 0 )
-              gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
-          }
-          else
-            gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
-
+        if ( next )
+          charcode = start;
+        else
           break;
-        }
       }
 
-      if ( !next || gindex )
+    Again:
+      if ( charcode <= end )
+      {
+        FT_Byte*  r;
+
+
+        r       = q - 2 + num_segs2;
+        delta   = TT_PEEK_SHORT( r );
+        r      += num_segs2;
+        offset  = TT_PEEK_USHORT( r );
+
+        /* some fonts have an incorrect last segment; */
+        /* we have to catch it                        */
+        if ( i >= num_segs - 1                  &&
+             start == 0xFFFFU && end == 0xFFFFU )
+        {
+          if ( offset && r + offset + 2 > limit )
+          {
+            delta  = 1;
+            offset = 0;
+          }
+        }
+
+        if ( offset == 0xFFFFU )
+          continue;
+
+        if ( offset )
+        {
+          r += offset + ( charcode - start ) * 2;
+
+          /* if r > limit, the whole segment is invalid */
+          if ( next && r > limit )
+            continue;
+
+          gindex = TT_PEEK_USHORT( r );
+          if ( gindex )
+          {
+            gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+            if ( gindex >= (FT_UInt)face->root.num_glyphs )
+              gindex = 0;
+          }
+        }
+        else
+        {
+          gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
+
+          if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
+          {
+            /* we have an invalid glyph index; if there is an overflow, */
+            /* we can adjust `charcode', otherwise the whole segment is */
+            /* invalid                                                  */
+            gindex = 0;
+
+            if ( (FT_Int)charcode + delta < 0 &&
+                 (FT_Int)end + delta >= 0     )
+              charcode = (FT_UInt)( -delta );
+
+            else if ( (FT_Int)charcode + delta < 0x10000L &&
+                      (FT_Int)end + delta >= 0x10000L     )
+              charcode = (FT_UInt)( 0x10000L - delta );
+
+            else
+              continue;
+          }
+        }
+
+        if ( next && !gindex )
+        {
+          if ( charcode >= 0xFFFFU )
+            break;
+
+          charcode++;
+          goto Again;
+        }
+
         break;
+      }
     }
 
-    if ( next && gindex )
+    if ( next )
       *pcharcode = charcode;
 
     return gindex;
@@ -1115,6 +1197,9 @@
                             FT_UInt32*  pcharcode,
                             FT_Bool     next )
   {
+    TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
+    FT_Byte*  limit = face->cmap_table + face->cmap_size;
+
     FT_UInt   num_segs2, start, end, offset;
     FT_Int    delta;
     FT_UInt   max, min, mid, num_segs;
@@ -1166,10 +1251,6 @@
         if ( mid >= num_segs - 1                &&
              start == 0xFFFFU && end == 0xFFFFU )
         {
-          TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
-          FT_Byte*  limit = face->cmap_table + face->cmap_size;
-
-
           if ( offset && p + offset + 2 > limit )
           {
             delta  = 1;
@@ -1190,7 +1271,7 @@
             mid = max + 1;
 
           /* search in segments before the current segment */
-          for ( i = max ; i > 0; i-- )
+          for ( i = max; i > 0; i-- )
           {
             FT_UInt   prev_end;
             FT_Byte*  old_p;
@@ -1292,12 +1373,39 @@
         if ( offset )
         {
           p += offset + ( charcode - start ) * 2;
+
+          /* if p > limit, the whole segment is invalid */
+          if ( next && p > limit )
+            break;
+
           gindex = TT_PEEK_USHORT( p );
-          if ( gindex != 0 )
-            gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+          if ( gindex )
+          {
+            gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+            if ( gindex >= (FT_UInt)face->root.num_glyphs )
+              gindex = 0;
+          }
         }
         else
-          gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
+        {
+          gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
+
+          if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
+          {
+            /* we have an invalid glyph index; if there is an overflow, */
+            /* we can adjust `charcode', otherwise the whole segment is */
+            /* invalid                                                  */
+            gindex = 0;
+
+            if ( (FT_Int)charcode + delta < 0 &&
+                 (FT_Int)end + delta >= 0     )
+              charcode = (FT_UInt)( -delta );
+
+            else if ( (FT_Int)charcode + delta < 0x10000L &&
+                      (FT_Int)end + delta >= 0x10000L     )
+              charcode = (FT_UInt)( 0x10000L - delta );
+          }
+        }
 
         break;
       }
@@ -1310,7 +1418,6 @@
 
       /* if `charcode' is not in any segment, then `mid' is */
       /* the segment nearest to `charcode'                  */
-      /*                                                    */
 
       if ( charcode > end )
       {
@@ -1443,7 +1550,7 @@
   /*                                                                       */
   /*   NAME        OFFSET          TYPE             DESCRIPTION            */
   /*                                                                       */
-  /*   format       0              USHORT           must be 4              */
+  /*   format       0              USHORT           must be 6              */
   /*   length       2              USHORT           table length in bytes  */
   /*   language     4              USHORT           Mac language code      */
   /*                                                                       */
@@ -1511,6 +1618,7 @@
       p += 2 * idx;
       result = TT_PEEK_USHORT( p );
     }
+
     return result;
   }
 
@@ -1531,7 +1639,7 @@
 
 
     if ( char_code >= 0x10000UL )
-      goto Exit;
+      return 0;
 
     if ( char_code < start )
       char_code = start;
@@ -1547,10 +1655,13 @@
         result = char_code;
         break;
       }
+
+      if ( char_code >= 0xFFFFU )
+        return 0;
+
       char_code++;
     }
 
-  Exit:
     *pchar_code = result;
     return gindex;
   }
@@ -1602,7 +1713,7 @@
   /*****                                                               *****/
   /***** The purpose of this format is to easily map UTF-16 text to    *****/
   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
-  /***** the following formats:                                        *****/
+  /***** the following formats.                                        *****/
   /*****                                                               *****/
   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
@@ -1615,7 +1726,7 @@
   /***** The `is32' table embedded in the charmap indicates whether a  *****/
   /***** given 16-bit value is in the surrogates area or not.          *****/
   /*****                                                               *****/
-  /***** So, for any given `char_code', we can assert the following:   *****/
+  /***** So, for any given `char_code', we can assert the following.   *****/
   /*****                                                               *****/
   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
   /*****                                                               *****/
@@ -1669,7 +1780,8 @@
     p          = is32  + 8192;          /* skip `is32' array */
     num_groups = TT_NEXT_ULONG( p );
 
-    if ( p + num_groups * 12 > valid->limit )
+    /* p + num_groups * 12 > valid->limit ? */
+    if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
       FT_INVALID_TOO_SHORT;
 
     /* check groups, they must be in increasing order */
@@ -1694,7 +1806,12 @@
 
         if ( valid->level >= FT_VALIDATE_TIGHT )
         {
-          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+          FT_UInt32  d = end - start;
+
+
+          /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
+          if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
+               start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
             FT_INVALID_GLYPH_ID;
 
           count = (FT_UInt32)( end - start + 1 );
@@ -1764,7 +1881,10 @@
 
       if ( char_code <= end )
       {
-        result = (FT_UInt)( start_id + char_code - start );
+        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+          return 0;
+
+        result = (FT_UInt)( start_id + ( char_code - start ) );
         break;
       }
     }
@@ -1776,8 +1896,9 @@
   tt_cmap8_char_next( TT_CMap     cmap,
                       FT_UInt32  *pchar_code )
   {
+    FT_Face    face       = cmap->cmap.charmap.face;
     FT_UInt32  result     = 0;
-    FT_UInt32  char_code  = *pchar_code + 1;
+    FT_UInt32  char_code;
     FT_UInt    gindex     = 0;
     FT_Byte*   table      = cmap->data;
     FT_Byte*   p          = table + 8204;
@@ -1785,6 +1906,11 @@
     FT_UInt32  start, end, start_id;
 
 
+    if ( *pchar_code >= 0xFFFFFFFFUL )
+      return 0;
+
+    char_code = *pchar_code + 1;
+
     p = table + 8208;
 
     for ( ; num_groups > 0; num_groups-- )
@@ -1796,18 +1922,38 @@
       if ( char_code < start )
         char_code = start;
 
+    Again:
       if ( char_code <= end )
       {
-        gindex = (FT_UInt)( char_code - start + start_id );
-        if ( gindex != 0 )
+        /* ignore invalid group */
+        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+          continue;
+
+        gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+        /* does first element of group point to `.notdef' glyph? */
+        if ( gindex == 0 )
         {
-          result = char_code;
-          goto Exit;
+          if ( char_code >= 0xFFFFFFFFUL )
+            break;
+
+          char_code++;
+          goto Again;
         }
+
+        /* if `gindex' is invalid, the remaining values */
+        /* in this group are invalid, too               */
+        if ( gindex >= (FT_UInt)face->num_glyphs )
+        {
+          gindex = 0;
+          continue;
+        }
+
+        result = char_code;
+        break;
       }
     }
 
-  Exit:
     *pchar_code = result;
     return gindex;
   }
@@ -1892,7 +2038,9 @@
     count  = TT_NEXT_ULONG( p );
 
     if ( length > (FT_ULong)( valid->limit - table ) ||
-         length < 20 + count * 2                     )
+         /* length < 20 + count * 2 ? */
+         length < 20                                 ||
+         ( length - 20 ) / 2 < count                 )
       FT_INVALID_TOO_SHORT;
 
     /* check glyph indices */
@@ -1922,14 +2070,20 @@
     FT_Byte*   p      = table + 12;
     FT_UInt32  start  = TT_NEXT_ULONG( p );
     FT_UInt32  count  = TT_NEXT_ULONG( p );
-    FT_UInt32  idx    = (FT_ULong)( char_code - start );
+    FT_UInt32  idx;
 
 
+    if ( char_code < start )
+      return 0;
+
+    idx = char_code - start;
+
     if ( idx < count )
     {
       p     += 2 * idx;
       result = TT_PEEK_USHORT( p );
     }
+
     return result;
   }
 
@@ -1939,7 +2093,7 @@
                        FT_UInt32  *pchar_code )
   {
     FT_Byte*   table     = cmap->data;
-    FT_UInt32  char_code = *pchar_code + 1;
+    FT_UInt32  char_code;
     FT_UInt    gindex    = 0;
     FT_Byte*   p         = table + 12;
     FT_UInt32  start     = TT_NEXT_ULONG( p );
@@ -1947,10 +2101,15 @@
     FT_UInt32  idx;
 
 
+    if ( *pchar_code >= 0xFFFFFFFFUL )
+      return 0;
+
+    char_code = *pchar_code + 1;
+
     if ( char_code < start )
       char_code = start;
 
-    idx = (FT_UInt32)( char_code - start );
+    idx = char_code - start;
     p  += 2 * idx;
 
     for ( ; idx < count; idx++ )
@@ -1958,6 +2117,10 @@
       gindex = TT_NEXT_USHORT( p );
       if ( gindex != 0 )
         break;
+
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
     }
 
@@ -2079,7 +2242,9 @@
     num_groups = TT_NEXT_ULONG( p );
 
     if ( length > (FT_ULong)( valid->limit - table ) ||
-         length < 16 + 12 * num_groups               )
+         /* length < 16 + 12 * num_groups ? */
+         length < 16                                 ||
+         ( length - 16 ) / 12 < num_groups           )
       FT_INVALID_TOO_SHORT;
 
     /* check groups, they must be in increasing order */
@@ -2101,7 +2266,12 @@
 
         if ( valid->level >= FT_VALIDATE_TIGHT )
         {
-          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+          FT_UInt32  d = end - start;
+
+
+          /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
+          if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
+               start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
             FT_INVALID_GLYPH_ID;
         }
 
@@ -2119,6 +2289,7 @@
   static void
   tt_cmap12_next( TT_CMap12  cmap )
   {
+    FT_Face   face = cmap->cmap.cmap.charmap.face;
     FT_Byte*  p;
     FT_ULong  start, end, start_id, char_code;
     FT_ULong  n;
@@ -2140,18 +2311,38 @@
       if ( char_code < start )
         char_code = start;
 
-      for ( ; char_code <= end; char_code++ )
+    Again:
+      if ( char_code <= end )
       {
-        gindex = (FT_UInt)( start_id + char_code - start );
+        /* ignore invalid group */
+        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+          continue;
 
-        if ( gindex )
+        gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+        /* does first element of group point to `.notdef' glyph? */
+        if ( gindex == 0 )
         {
-          cmap->cur_charcode = char_code;;
-          cmap->cur_gindex   = gindex;
-          cmap->cur_group    = n;
+          if ( char_code >= 0xFFFFFFFFUL )
+            goto Fail;
 
-          return;
+          char_code++;
+          goto Again;
         }
+
+        /* if `gindex' is invalid, the remaining values */
+        /* in this group are invalid, too               */
+        if ( gindex >= (FT_UInt)face->num_glyphs )
+        {
+          gindex = 0;
+          continue;
+        }
+
+        cmap->cur_charcode = char_code;
+        cmap->cur_gindex   = gindex;
+        cmap->cur_group    = n;
+
+        return;
       }
     }
 
@@ -2181,7 +2372,12 @@
     end = 0xFFFFFFFFUL;
 
     if ( next )
+    {
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
+    }
 
     min = 0;
     max = num_groups;
@@ -2202,20 +2398,24 @@
       else
       {
         start_id = TT_PEEK_ULONG( p );
-        gindex = (FT_UInt)( start_id + char_code - start );
 
+        /* reject invalid glyph index */
+        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+          gindex = 0;
+        else
+          gindex = (FT_UInt)( start_id + ( char_code - start ) );
         break;
       }
     }
 
     if ( next )
     {
+      FT_Face    face   = cmap->cmap.charmap.face;
       TT_CMap12  cmap12 = (TT_CMap12)cmap;
 
 
       /* if `char_code' is not in any group, then `mid' is */
       /* the group nearest to `char_code'                  */
-      /*                                                   */
 
       if ( char_code > end )
       {
@@ -2228,6 +2428,9 @@
       cmap12->cur_charcode = char_code;
       cmap12->cur_group    = mid;
 
+      if ( gindex >= (FT_UInt)face->num_glyphs )
+        gindex = 0;
+
       if ( !gindex )
       {
         tt_cmap12_next( cmap12 );
@@ -2238,8 +2441,7 @@
       else
         cmap12->cur_gindex = gindex;
 
-      if ( gindex )
-        *pchar_code = cmap12->cur_charcode;
+      *pchar_code = cmap12->cur_charcode;
     }
 
     return gindex;
@@ -2259,23 +2461,17 @@
                        FT_UInt32  *pchar_code )
   {
     TT_CMap12  cmap12 = (TT_CMap12)cmap;
-    FT_ULong   gindex;
+    FT_UInt    gindex;
 
 
-    if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
-      return 0;
-
     /* no need to search */
     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
     {
       tt_cmap12_next( cmap12 );
       if ( cmap12->valid )
       {
-        gindex = cmap12->cur_gindex;
-
-        /* XXX: check cur_charcode overflow is expected */
-        if ( gindex )
-          *pchar_code = (FT_UInt32)cmap12->cur_charcode;
+        gindex      = cmap12->cur_gindex;
+        *pchar_code = (FT_UInt32)cmap12->cur_charcode;
       }
       else
         gindex = 0;
@@ -2283,8 +2479,7 @@
     else
       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
 
-    /* XXX: check gindex overflow is expected */
-    return (FT_UInt32)gindex;
+    return gindex;
   }
 
 
@@ -2401,7 +2596,9 @@
     num_groups = TT_NEXT_ULONG( p );
 
     if ( length > (FT_ULong)( valid->limit - table ) ||
-         length < 16 + 12 * num_groups               )
+         /* length < 16 + 12 * num_groups ? */
+         length < 16                                 ||
+         ( length - 16 ) / 12 < num_groups           )
       FT_INVALID_TOO_SHORT;
 
     /* check groups, they must be in increasing order */
@@ -2441,6 +2638,7 @@
   static void
   tt_cmap13_next( TT_CMap13  cmap )
   {
+    FT_Face   face = cmap->cmap.cmap.charmap.face;
     FT_Byte*  p;
     FT_ULong  start, end, glyph_id, char_code;
     FT_ULong  n;
@@ -2466,9 +2664,9 @@
       {
         gindex = (FT_UInt)glyph_id;
 
-        if ( gindex )
+        if ( gindex && gindex < (FT_UInt)face->num_glyphs )
         {
-          cmap->cur_charcode = char_code;;
+          cmap->cur_charcode = char_code;
           cmap->cur_gindex   = gindex;
           cmap->cur_group    = n;
 
@@ -2503,7 +2701,12 @@
     end = 0xFFFFFFFFUL;
 
     if ( next )
+    {
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
+    }
 
     min = 0;
     max = num_groups;
@@ -2531,6 +2734,7 @@
 
     if ( next )
     {
+      FT_Face    face   = cmap->cmap.charmap.face;
       TT_CMap13  cmap13 = (TT_CMap13)cmap;
 
 
@@ -2548,6 +2752,9 @@
       cmap13->cur_charcode = char_code;
       cmap13->cur_group    = mid;
 
+      if ( gindex >= (FT_UInt)face->num_glyphs )
+        gindex = 0;
+
       if ( !gindex )
       {
         tt_cmap13_next( cmap13 );
@@ -2558,8 +2765,7 @@
       else
         cmap13->cur_gindex = gindex;
 
-      if ( gindex )
-        *pchar_code = cmap13->cur_charcode;
+      *pchar_code = cmap13->cur_charcode;
     }
 
     return gindex;
@@ -2582,18 +2788,14 @@
     FT_UInt    gindex;
 
 
-    if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
-      return 0;
-
     /* no need to search */
     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
     {
       tt_cmap13_next( cmap13 );
       if ( cmap13->valid )
       {
-        gindex = cmap13->cur_gindex;
-        if ( gindex )
-          *pchar_code = cmap13->cur_charcode;
+        gindex      = cmap13->cur_gindex;
+        *pchar_code = cmap13->cur_charcode;
       }
       else
         gindex = 0;
@@ -2787,7 +2989,9 @@
     num_selectors = TT_NEXT_ULONG( p );
 
     if ( length > (FT_ULong)( valid->limit - table ) ||
-         length < 10 + 11 * num_selectors            )
+         /* length < 10 + 11 * num_selectors ? */
+         length < 10                                 ||
+         ( length - 10 ) / 11 < num_selectors        )
       FT_INVALID_TOO_SHORT;
 
     /* check selectors, they must be in increasing order */
@@ -2817,13 +3021,19 @@
         /* through the normal Unicode cmap, no GIDs, just check order) */
         if ( defOff != 0 )
         {
-          FT_Byte*  defp      = table + defOff;
-          FT_ULong  numRanges = TT_NEXT_ULONG( defp );
+          FT_Byte*  defp     = table + defOff;
+          FT_ULong  numRanges;
           FT_ULong  i;
-          FT_ULong  lastBase  = 0;
+          FT_ULong  lastBase = 0;
 
 
-          if ( defp + numRanges * 4 > valid->limit )
+          if ( defp + 4 > valid->limit )
+            FT_INVALID_TOO_SHORT;
+
+          numRanges = TT_NEXT_ULONG( defp );
+
+          /* defp + numRanges * 4 > valid->limit ? */
+          if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
             FT_INVALID_TOO_SHORT;
 
           for ( i = 0; i < numRanges; ++i )
@@ -2845,12 +3055,18 @@
         /* and the non-default table (these glyphs are specified here) */
         if ( nondefOff != 0 )
         {
-          FT_Byte*  ndp         = table + nondefOff;
-          FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
-          FT_ULong  i, lastUni  = 0;
+          FT_Byte*  ndp        = table + nondefOff;
+          FT_ULong  numMappings;
+          FT_ULong  i, lastUni = 0;
 
 
-          if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
+          if ( ndp + 4 > valid->limit )
+            FT_INVALID_TOO_SHORT;
+
+          numMappings = TT_NEXT_ULONG( ndp );
+
+          /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
+          if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
             FT_INVALID_TOO_SHORT;
 
           for ( i = 0; i < numMappings; ++i )
@@ -2941,7 +3157,7 @@
 
       if ( char_code < start )
         max = mid;
-      else if ( char_code > start+cnt )
+      else if ( char_code > start + cnt )
         min = mid + 1;
       else
         return TRUE;
@@ -3295,7 +3511,7 @@
       ni   = 1;
       i    = 0;
 
-      for ( ;; )
+      for (;;)
       {
         if ( nuni > duni + dcnt )
         {
@@ -3475,20 +3691,12 @@
     {
       FT_ERROR(( "tt_face_build_cmaps:"
                  " unsupported `cmap' table format = %d\n",
-                 TT_PEEK_USHORT( p - 2) ));
+                 TT_PEEK_USHORT( p - 2 ) ));
       return FT_THROW( Invalid_Table );
     }
 
     num_cmaps = TT_NEXT_USHORT( p );
 
-#ifdef FT_MAX_CHARMAP_CACHEABLE
-    if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
-      FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
-                 "                     subtable #%d and higher are loaded"
-                 "                     but cannot be searched\n",
-                 num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
-#endif
-
     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
     {
       FT_CharMapRec  charmap;
diff --git a/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h
index 0fde167..2273cbd 100644
--- a/src/sfnt/ttcmap.h
+++ b/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (specification).     */
 /*                                                                         */
-/*  Copyright 2002-2005, 2009, 2012 by                                     */
+/*  Copyright 2002-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTCMAP_H__
-#define __TTCMAP_H__
+#ifndef TTCMAP_H_
+#define TTCMAP_H_
 
 
 #include <ft2build.h>
@@ -152,7 +152,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTCMAP_H__ */
+#endif /* TTCMAP_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttcmapc.h b/src/sfnt/ttcmapc.h
index 2ea2043..7c732fb 100644
--- a/src/sfnt/ttcmapc.h
+++ b/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TT CMAP classes definitions (specification only).                    */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c
index 32c4008..6f9fa52 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-2007, 2009, 2010, 2013 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -99,7 +99,7 @@
       length   = FT_NEXT_USHORT( p );
       coverage = FT_NEXT_USHORT( p );
 
-      if ( length <= 6 )
+      if ( length <= 6 + 8 )
         break;
 
       p_next += length;
@@ -108,8 +108,8 @@
         p_next = p_limit;
 
       /* only use horizontal kerning tables */
-      if ( ( coverage & ~8 ) != 0x0001 ||
-           p + 8 > p_limit             )
+      if ( ( coverage & ~8U ) != 0x0001 ||
+           p + 8 > p_limit              )
         goto NextTable;
 
       num_pairs = FT_NEXT_USHORT( p );
diff --git a/src/sfnt/ttkern.h b/src/sfnt/ttkern.h
index df1da9b..85dd5c3 100644
--- a/src/sfnt/ttkern.h
+++ b/src/sfnt/ttkern.h
@@ -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, 2005, 2007 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTKERN_H__
-#define __TTKERN_H__
+#ifndef TTKERN_H_
+#define TTKERN_H_
 
 
 #include <ft2build.h>
@@ -46,7 +46,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTKERN_H__ */
+#endif /* TTKERN_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 0a3cd29..a653a71 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
 /*    TTF or OTF fonts (body).                                             */
 /*                                                                         */
-/*  Copyright 1996-2010, 2012, 2013 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -151,7 +151,8 @@
 
   /* Here, we                                                         */
   /*                                                                  */
-  /* - check that `num_tables' is valid (and adjust it if necessary)  */
+  /* - check that `num_tables' is valid (and adjust it if necessary); */
+  /*   also return the number of valid table entries                  */
   /*                                                                  */
   /* - look for a `head' table, check its size, and parse it to check */
   /*   whether its `magic' field is correctly set                     */
@@ -167,7 +168,8 @@
   /*                                                                  */
   static FT_Error
   check_table_dir( SFNT_Header  sfnt,
-                   FT_Stream    stream )
+                   FT_Stream    stream,
+                   FT_UShort*   valid )
   {
     FT_Error   error;
     FT_UShort  nn, valid_entries = 0;
@@ -207,11 +209,28 @@
       }
 
       /* we ignore invalid tables */
-      if ( table.Offset + table.Length > stream->size )
+
+      if ( table.Offset > stream->size )
       {
         FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
         continue;
       }
+      else if ( table.Length > stream->size - table.Offset )
+      {
+        /* Some tables have such a simple structure that clipping its     */
+        /* contents is harmless.  This also makes FreeType less sensitive */
+        /* to invalid table lengths (which programs like Acroread seem to */
+        /* ignore in general).                                            */
+
+        if ( table.Tag == TTAG_hmtx ||
+             table.Tag == TTAG_vmtx )
+          valid_entries++;
+        else
+        {
+          FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
+          continue;
+        }
+      }
       else
         valid_entries++;
 
@@ -259,11 +278,11 @@
         has_meta = 1;
     }
 
-    sfnt->num_tables = valid_entries;
+    *valid = valid_entries;
 
-    if ( sfnt->num_tables == 0 )
+    if ( !valid_entries )
     {
-      FT_TRACE2(( "check_table_dir: no tables found\n" ));
+      FT_TRACE2(( "check_table_dir: no valid tables found\n" ));
       error = FT_THROW( Unknown_File_Format );
       goto Exit;
     }
@@ -319,8 +338,7 @@
     SFNT_HeaderRec  sfnt;
     FT_Error        error;
     FT_Memory       memory = stream->memory;
-    TT_TableRec*    entry;
-    FT_Int          nn;
+    FT_UShort       nn, valid_entries;
 
     static const FT_Frame_Field  offset_table_fields[] =
     {
@@ -361,56 +379,114 @@
     if ( sfnt.format_tag != TTAG_OTTO )
     {
       /* check first */
-      error = check_table_dir( &sfnt, stream );
+      error = check_table_dir( &sfnt, stream, &valid_entries );
       if ( error )
       {
         FT_TRACE2(( "tt_face_load_font_dir:"
                     " invalid table directory for TrueType\n" ));
-
         goto Exit;
       }
     }
+    else
+      valid_entries = sfnt.num_tables;
 
-    face->num_tables = sfnt.num_tables;
+    face->num_tables = valid_entries;
     face->format_tag = sfnt.format_tag;
 
     if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
       goto Exit;
 
-    if ( FT_STREAM_SEEK( sfnt.offset + 12 )       ||
-         FT_FRAME_ENTER( face->num_tables * 16L ) )
+    if ( FT_STREAM_SEEK( sfnt.offset + 12 )      ||
+         FT_FRAME_ENTER( sfnt.num_tables * 16L ) )
       goto Exit;
 
-    entry = face->dir_tables;
-
     FT_TRACE2(( "\n"
                 "  tag    offset    length   checksum\n"
                 "  ----------------------------------\n" ));
 
+    valid_entries = 0;
     for ( nn = 0; nn < sfnt.num_tables; nn++ )
     {
-      entry->Tag      = FT_GET_TAG4();
-      entry->CheckSum = FT_GET_ULONG();
-      entry->Offset   = FT_GET_ULONG();
-      entry->Length   = FT_GET_ULONG();
+      TT_TableRec  entry;
+      FT_UShort    i;
+      FT_Bool      duplicate;
 
-      /* ignore invalid tables */
-      if ( entry->Offset + entry->Length > stream->size )
+
+      entry.Tag      = FT_GET_TAG4();
+      entry.CheckSum = FT_GET_ULONG();
+      entry.Offset   = FT_GET_ULONG();
+      entry.Length   = FT_GET_ULONG();
+
+      /* ignore invalid tables that can't be sanitized */
+
+      if ( entry.Offset > stream->size )
         continue;
+      else if ( entry.Length > stream->size - entry.Offset )
+      {
+        if ( entry.Tag == TTAG_hmtx ||
+             entry.Tag == TTAG_vmtx )
+        {
+#ifdef FT_DEBUG_LEVEL_TRACE
+          FT_ULong  old_length = entry.Length;
+#endif
+
+
+          /* make metrics table length a multiple of 4 */
+          entry.Length = ( stream->size - entry.Offset ) & ~3U;
+
+          FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx"
+                      " (sanitized; original length %08lx)",
+                      (FT_Char)( entry.Tag >> 24 ),
+                      (FT_Char)( entry.Tag >> 16 ),
+                      (FT_Char)( entry.Tag >> 8  ),
+                      (FT_Char)( entry.Tag       ),
+                      entry.Offset,
+                      entry.Length,
+                      entry.CheckSum,
+                      old_length ));
+        }
+        else
+          continue;
+      }
+#ifdef FT_DEBUG_LEVEL_TRACE
+      else
+        FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx",
+                    (FT_Char)( entry.Tag >> 24 ),
+                    (FT_Char)( entry.Tag >> 16 ),
+                    (FT_Char)( entry.Tag >> 8  ),
+                    (FT_Char)( entry.Tag       ),
+                    entry.Offset,
+                    entry.Length,
+                    entry.CheckSum ));
+#endif
+
+      /* ignore duplicate tables – the first one wins */
+      duplicate = 0;
+      for ( i = 0; i < valid_entries; i++ )
+      {
+        if ( face->dir_tables[i].Tag == entry.Tag )
+        {
+          duplicate = 1;
+          break;
+        }
+      }
+      if ( duplicate )
+      {
+        FT_TRACE2(( "  (duplicate, ignored)\n" ));
+        continue;
+      }
       else
       {
-        FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx\n",
-                    (FT_Char)( entry->Tag >> 24 ),
-                    (FT_Char)( entry->Tag >> 16 ),
-                    (FT_Char)( entry->Tag >> 8  ),
-                    (FT_Char)( entry->Tag       ),
-                    entry->Offset,
-                    entry->Length,
-                    entry->CheckSum ));
-        entry++;
+        FT_TRACE2(( "\n" ));
+
+        /* we finally have a valid entry */
+        face->dir_tables[valid_entries++] = entry;
       }
     }
 
+    /* final adjustment to number of tables */
+    face->num_tables = valid_entries;
+
     FT_FRAME_EXIT();
 
     FT_TRACE2(( "table directory loaded\n\n" ));
@@ -699,15 +775,6 @@
 
         maxProfile->maxTwilightPoints = 0xFFFFU - 4;
       }
-
-      /* we arbitrarily limit recursion to avoid stack exhaustion */
-      if ( maxProfile->maxComponentDepth > 100 )
-      {
-        FT_TRACE0(( "tt_face_load_maxp:"
-                    " abnormally large component depth (%d) set to 100\n",
-                    maxProfile->maxComponentDepth ));
-        maxProfile->maxComponentDepth = 100;
-      }
     }
 
     FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
@@ -1117,8 +1184,8 @@
 #define FT_STRUCTURE  TT_Postscript
 
       FT_FRAME_START( 32 ),
-        FT_FRAME_ULONG( FormatType ),
-        FT_FRAME_ULONG( italicAngle ),
+        FT_FRAME_LONG ( FormatType ),
+        FT_FRAME_LONG ( italicAngle ),
         FT_FRAME_SHORT( underlinePosition ),
         FT_FRAME_SHORT( underlineThickness ),
         FT_FRAME_ULONG( isFixedPitch ),
diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h
index 49a1aee..bec42b9 100644
--- a/src/sfnt/ttload.h
+++ b/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
 /*    TTF or OTF fonts (specification).                                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2005, 2006 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTLOAD_H__
-#define __TTLOAD_H__
+#ifndef TTLOAD_H_
+#define TTLOAD_H_
 
 
 #include <ft2build.h>
@@ -106,7 +106,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTLOAD_H__ */
+#endif /* TTLOAD_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index a8cc63a..186f873 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Load the metrics tables common to TTF and OTF fonts (body).          */
 /*                                                                         */
-/*  Copyright 2006-2009, 2011-2013 by                                      */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -201,7 +201,7 @@
   /*    aadvance :: The advance width or advance height, depending on      */
   /*                the `vertical' flag.                                   */
   /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   tt_face_get_metrics( TT_Face     face,
                        FT_Bool     vertical,
                        FT_UInt     gindex,
@@ -274,8 +274,6 @@
       *abearing = 0;
       *aadvance = 0;
     }
-
-    return FT_Err_Ok;
   }
 
 
diff --git a/src/sfnt/ttmtx.h b/src/sfnt/ttmtx.h
index 8b91a11..78395de 100644
--- a/src/sfnt/ttmtx.h
+++ b/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Load the metrics tables common to TTF and OTF fonts (specification). */
 /*                                                                         */
-/*  Copyright 2006 by                                                      */
+/*  Copyright 2006-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTMTX_H__
-#define __TTMTX_H__
+#ifndef TTMTX_H_
+#define TTMTX_H_
 
 
 #include <ft2build.h>
@@ -40,7 +40,7 @@
                      FT_Bool    vertical );
 
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   tt_face_get_metrics( TT_Face     face,
                        FT_Bool     vertical,
                        FT_UInt     gindex,
@@ -49,7 +49,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTMTX_H__ */
+#endif /* TTMTX_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index 99d8005..3277f1e 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -2,10 +2,10 @@
 /*                                                                         */
 /*  ttpost.c                                                               */
 /*                                                                         */
-/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    PostScript name table processing for TrueType and OpenType fonts     */
 /*    (body).                                                              */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006-2010, 2013, 2014 by                          */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -52,7 +52,7 @@
 
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
-#define MAC_NAME( x )  ( (FT_String*)psnames->macintosh_name( x ) )
+#define MAC_NAME( x )  (FT_String*)psnames->macintosh_name( (FT_UInt)(x) )
 
 
 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -62,7 +62,7 @@
    /* table of Mac names.  Thus, it is possible to build a version of */
    /* FreeType without the Type 1 driver & PSNames module.            */
 
-#define MAC_NAME( x )  ( (FT_String*)tt_post_default_names[x] )
+#define MAC_NAME( x )  (FT_String*)tt_post_default_names[x]
 
   /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */
 
@@ -155,7 +155,7 @@
   static FT_Error
   load_format_20( TT_Face    face,
                   FT_Stream  stream,
-                  FT_Long    post_limit )
+                  FT_ULong   post_limit )
   {
     FT_Memory   memory = stream->memory;
     FT_Error    error;
@@ -163,8 +163,8 @@
     FT_Int      num_glyphs;
     FT_UShort   num_names;
 
-    FT_UShort*  glyph_indices = 0;
-    FT_Char**   name_strings  = 0;
+    FT_UShort*  glyph_indices = NULL;
+    FT_Char**   name_strings  = NULL;
 
 
     if ( FT_READ_USHORT( num_glyphs ) )
@@ -243,14 +243,17 @@
             goto Fail1;
         }
 
-        if ( (FT_Int)len > post_limit                   ||
-             FT_STREAM_POS() > post_limit - (FT_Int)len )
+        if ( len > post_limit                   ||
+             FT_STREAM_POS() > post_limit - len )
         {
+          FT_Int  d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS();
+
+
           FT_ERROR(( "load_format_20:"
                      " exceeding string length (%d),"
                      " truncating at end of post table (%d byte left)\n",
-                     len, post_limit - FT_STREAM_POS() ));
-          len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
+                     len, d ));
+          len = (FT_UInt)FT_MAX( 0, d );
         }
 
         if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
@@ -307,13 +310,13 @@
   static FT_Error
   load_format_25( TT_Face    face,
                   FT_Stream  stream,
-                  FT_Long    post_limit )
+                  FT_ULong   post_limit )
   {
     FT_Memory  memory = stream->memory;
     FT_Error   error;
 
     FT_Int     num_glyphs;
-    FT_Char*   offset_table = 0;
+    FT_Char*   offset_table = NULL;
 
     FT_UNUSED( post_limit );
 
@@ -377,7 +380,7 @@
     FT_Error   error;
     FT_Fixed   format;
     FT_ULong   post_len;
-    FT_Long    post_limit;
+    FT_ULong   post_limit;
 
 
     /* get a stream for the face's resource */
@@ -547,10 +550,7 @@
       }
 
       if ( idx < (FT_UInt)table->num_glyphs )    /* paranoid checking */
-      {
-        idx    += table->offsets[idx];
-        *PSname = MAC_NAME( idx );
-      }
+        *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] );
     }
 
     /* nothing to do for format == 0x00030000L */
diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h
index 6f06d75..ede45fd 100644
--- a/src/sfnt/ttpost.h
+++ b/src/sfnt/ttpost.h
@@ -2,10 +2,10 @@
 /*                                                                         */
 /*  ttpost.h                                                               */
 /*                                                                         */
-/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    PostScript name table processing for TrueType and OpenType fonts     */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTPOST_H__
-#define __TTPOST_H__
+#ifndef TTPOST_H_
+#define TTPOST_H_
 
 
 #include <ft2build.h>
@@ -40,7 +40,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTPOST_H__ */
+#endif /* TTPOST_H_ */
 
 
 /* END */
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index 180d559..0a90111 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded bitmap support (body).                */
 /*                                                                         */
-/*  Copyright 2005-2009, 2013, 2014 by                                     */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  Copyright 2013 by Google, Inc.                                         */
@@ -101,10 +101,11 @@
 
         p = face->sbit_table;
 
-        version     = FT_NEXT_ULONG( p );
+        version     = FT_NEXT_LONG( p );
         num_strikes = FT_NEXT_ULONG( p );
 
-        if ( ( version & 0xFFFF0000UL ) != 0x00020000UL )
+        if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL &&
+             ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL )
         {
           error = FT_THROW( Unknown_File_Format );
           goto Exit;
@@ -150,12 +151,25 @@
           error = FT_THROW( Unknown_File_Format );
           goto Exit;
         }
-        if ( flags != 0x0001 || num_strikes >= 0x10000UL )
+
+        /* Bit 0 must always be `1'.                            */
+        /* Bit 1 controls the overlay of bitmaps with outlines. */
+        /* All other bits should be zero.                       */
+        if ( !( flags == 1 || flags == 3 ) ||
+             num_strikes >= 0x10000UL      )
         {
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
+        /* we currently don't support bit 1; however, it is better to */
+        /* draw at least something...                                 */
+        if ( flags == 3 )
+          FT_TRACE1(( "tt_face_load_sbit_strikes:"
+                      " sbix overlay not supported yet\n"
+                      "                          "
+                      " expect bad rendering results\n" ));
+
         /*
          *  Count the number of strikes available in the table.  We are a bit
          *  paranoid there and don't trust the data.
@@ -183,6 +197,27 @@
     if ( !error )
       FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
 
+    face->ebdt_start = 0;
+    face->ebdt_size  = 0;
+
+    if ( face->sbit_table_type != TT_SBIT_TABLE_TYPE_NONE )
+    {
+      FT_ULong  ebdt_size;
+
+
+      error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size );
+      if ( error )
+        error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
+      if ( error )
+        error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
+
+      if ( !error )
+      {
+        face->ebdt_start = FT_STREAM_POS();
+        face->ebdt_size  = ebdt_size;
+      }
+    }
+
     return FT_Err_Ok;
 
   Exit:
@@ -225,8 +260,22 @@
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics )
   {
-    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
-      return FT_THROW( Invalid_Argument );
+    /* we have to test for the existence of `sbit_strike_map'    */
+    /* because the function gets also used at the very beginning */
+    /* to construct `sbit_strike_map' itself                     */
+    if ( face->sbit_strike_map )
+    {
+      if ( strike_index >= (FT_ULong)face->root.num_fixed_sizes )
+        return FT_THROW( Invalid_Argument );
+
+      /* map to real index */
+      strike_index = face->sbit_strike_map[strike_index];
+    }
+    else
+    {
+      if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
+        return FT_THROW( Invalid_Argument );
+    }
 
     switch ( (FT_UInt)face->sbit_table_type )
     {
@@ -234,6 +283,8 @@
     case TT_SBIT_TABLE_TYPE_CBLC:
       {
         FT_Byte*  strike;
+        FT_Char   max_before_bl;
+        FT_Char   min_after_bl;
 
 
         strike = face->sbit_table + 8 + strike_index * 48;
@@ -241,25 +292,94 @@
         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;
+        metrics->ascender  = (FT_Char)strike[16] * 64;  /* hori.ascender  */
+        metrics->descender = (FT_Char)strike[17] * 64;  /* hori.descender */
+
+        /* Due to fuzzy wording in the EBLC documentation, we find both */
+        /* positive and negative values for `descender'.  Additionally, */
+        /* many fonts have both `ascender' and `descender' set to zero  */
+        /* (which is definitely wrong).  MS Windows simply ignores all  */
+        /* those values...  For these reasons we apply some heuristics  */
+        /* to get a reasonable, non-zero value for the height.          */
+
+        max_before_bl = (FT_Char)strike[24];
+        min_after_bl  = (FT_Char)strike[25];
+
+        if ( metrics->descender > 0 )
+        {
+          /* compare sign of descender with `min_after_bl' */
+          if ( min_after_bl < 0 )
+            metrics->descender = -metrics->descender;
+        }
+
+        else if ( metrics->descender == 0 )
+        {
+          if ( metrics->ascender == 0 )
+          {
+            FT_TRACE2(( "tt_face_load_strike_metrics:"
+                        " sanitizing invalid ascender and descender\n"
+                        "                            "
+                        " values for strike %d (%dppem, %dppem)\n",
+                        strike_index,
+                        metrics->x_ppem, metrics->y_ppem ));
+
+            /* sanitize buggy ascender and descender values */
+            if ( max_before_bl || min_after_bl )
+            {
+              metrics->ascender  = max_before_bl * 64;
+              metrics->descender = min_after_bl * 64;
+            }
+            else
+            {
+              metrics->ascender  = metrics->y_ppem * 64;
+              metrics->descender = 0;
+            }
+          }
+        }
+
+#if 0
+        else
+          ; /* if we have a negative descender, simply use it */
+#endif
+
+        metrics->height = metrics->ascender - metrics->descender;
+        if ( metrics->height == 0 )
+        {
+          FT_TRACE2(( "tt_face_load_strike_metrics:"
+                      " sanitizing invalid height value\n"
+                      "                            "
+                      " for strike (%d, %d)\n",
+                      metrics->x_ppem, metrics->y_ppem ));
+          metrics->height    = metrics->y_ppem * 64;
+          metrics->descender = metrics->ascender - metrics->height;
+        }
 
         /* 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;
+                                                     ) * 64;
+
+        /* set the scale values (in 16.16 units) so advances */
+        /* from the hmtx and vmtx table are scaled correctly */
+        metrics->x_scale = FT_MulDiv( metrics->x_ppem,
+                                      64 * 0x10000,
+                                      face->header.Units_Per_EM );
+        metrics->y_scale = FT_MulDiv( metrics->y_ppem,
+                                      64 * 0x10000,
+                                      face->header.Units_Per_EM );
+
         return FT_Err_Ok;
       }
 
     case TT_SBIT_TABLE_TYPE_SBIX:
       {
         FT_Stream       stream = face->root.stream;
-        FT_UInt         offset, upem;
-        FT_UShort       ppem, resolution;
+        FT_UInt         offset;
+        FT_UShort       upem, ppem, resolution;
         TT_HoriHeader  *hori;
         FT_ULong        table_size;
+        FT_Pos          ppem_; /* to reduce casts */
 
         FT_Error  error;
         FT_Byte*  p;
@@ -292,12 +412,17 @@
         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;
+        ppem_ = (FT_Pos)ppem;
+
+        metrics->ascender =
+          FT_MulDiv( hori->Ascender, ppem_ * 64, upem );
+        metrics->descender =
+          FT_MulDiv( hori->Descender, ppem_ * 64, upem );
+        metrics->height =
+          FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap,
+                     ppem_ * 64, upem );
+        metrics->max_advance =
+          FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem );
 
         return error;
       }
@@ -335,17 +460,15 @@
                         FT_ULong             strike_index,
                         TT_SBit_MetricsRec*  metrics )
   {
-    FT_Error   error;
+    FT_Error   error  = FT_ERR( Table_Missing );
     FT_Stream  stream = face->root.stream;
-    FT_ULong   ebdt_size;
 
 
-    error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size );
-    if ( error )
-      error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
-    if ( error )
-      error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
-    if ( error )
+    strike_index = face->sbit_strike_map[strike_index];
+
+    if ( !face->ebdt_size )
+      goto Exit;
+    if ( FT_STREAM_SEEK( face->ebdt_start ) )
       goto Exit;
 
     decoder->face    = face;
@@ -356,8 +479,8 @@
     decoder->metrics_loaded   = 0;
     decoder->bitmap_allocated = 0;
 
-    decoder->ebdt_start = FT_STREAM_POS();
-    decoder->ebdt_size  = ebdt_size;
+    decoder->ebdt_start = face->ebdt_start;
+    decoder->ebdt_size  = face->ebdt_size;
 
     decoder->eblc_base  = face->sbit_table;
     decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
@@ -381,9 +504,11 @@
       p                          += 34;
       decoder->bit_depth          = *p;
 
-      if ( decoder->strike_index_array > face->sbit_table_size             ||
-           decoder->strike_index_array + 8 * decoder->strike_index_count >
-             face->sbit_table_size                                         )
+      /* decoder->strike_index_array +                               */
+      /*   8 * decoder->strike_index_count > face->sbit_table_size ? */
+      if ( decoder->strike_index_array > face->sbit_table_size           ||
+           decoder->strike_index_count >
+             ( face->sbit_table_size - decoder->strike_index_array ) / 8 )
         error = FT_THROW( Invalid_File_Format );
     }
 
@@ -405,7 +530,7 @@
     FT_Error    error = FT_Err_Ok;
     FT_UInt     width, height;
     FT_Bitmap*  map = decoder->bitmap;
-    FT_Long     size;
+    FT_ULong    size;
 
 
     if ( !decoder->metrics_loaded )
@@ -417,38 +542,38 @@
     width  = decoder->metrics->width;
     height = decoder->metrics->height;
 
-    map->width = (int)width;
-    map->rows  = (int)height;
+    map->width = width;
+    map->rows  = height;
 
     switch ( decoder->bit_depth )
     {
     case 1:
       map->pixel_mode = FT_PIXEL_MODE_MONO;
-      map->pitch      = ( map->width + 7 ) >> 3;
+      map->pitch      = (int)( ( map->width + 7 ) >> 3 );
       map->num_grays  = 2;
       break;
 
     case 2:
       map->pixel_mode = FT_PIXEL_MODE_GRAY2;
-      map->pitch      = ( map->width + 3 ) >> 2;
+      map->pitch      = (int)( ( map->width + 3 ) >> 2 );
       map->num_grays  = 4;
       break;
 
     case 4:
       map->pixel_mode = FT_PIXEL_MODE_GRAY4;
-      map->pitch      = ( map->width + 1 ) >> 1;
+      map->pitch      = (int)( ( map->width + 1 ) >> 1 );
       map->num_grays  = 16;
       break;
 
     case 8:
       map->pixel_mode = FT_PIXEL_MODE_GRAY;
-      map->pitch      = map->width;
+      map->pitch      = (int)( map->width );
       map->num_grays  = 256;
       break;
 
     case 32:
       map->pixel_mode = FT_PIXEL_MODE_BGRA;
-      map->pitch      = map->width * 4;
+      map->pitch      = (int)( map->width * 4 );
       map->num_grays  = 256;
       break;
 
@@ -457,7 +582,7 @@
       goto Exit;
     }
 
-    size = map->rows * map->pitch;
+    size = map->rows * (FT_ULong)map->pitch;
 
     /* check that there is no empty image */
     if ( size == 0 )
@@ -505,13 +630,20 @@
 
       p += 3;
     }
+    else
+    {
+      /* avoid uninitialized data in case there is no vertical info -- */
+      metrics->vertBearingX = 0;
+      metrics->vertBearingY = 0;
+      metrics->vertAdvance  = 0;
+    }
 
     decoder->metrics_loaded = 1;
     *pp = p;
     return FT_Err_Ok;
 
   Fail:
-    FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" ));
+    FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table\n" ));
     return FT_THROW( Invalid_Argument );
   }
 
@@ -521,13 +653,16 @@
   tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
                               FT_UInt         glyph_index,
                               FT_Int          x_pos,
-                              FT_Int          y_pos );
+                              FT_Int          y_pos,
+                              FT_UInt         recurse_count );
 
-  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder  decoder,
-                                                FT_Byte*        p,
-                                                FT_Byte*        plimit,
-                                                FT_Int          x_pos,
-                                                FT_Int          y_pos );
+  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)(
+                      TT_SBitDecoder  decoder,
+                      FT_Byte*        p,
+                      FT_Byte*        plimit,
+                      FT_Int          x_pos,
+                      FT_Int          y_pos,
+                      FT_UInt         recurse_count );
 
 
   static FT_Error
@@ -535,13 +670,17 @@
                                      FT_Byte*        p,
                                      FT_Byte*        limit,
                                      FT_Int          x_pos,
-                                     FT_Int          y_pos )
+                                     FT_Int          y_pos,
+                                     FT_UInt         recurse_count )
   {
     FT_Error    error = FT_Err_Ok;
     FT_Byte*    line;
-    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h;
+    FT_Int      pitch, width, height, line_bits, h;
+    FT_UInt     bit_height, bit_width;
     FT_Bitmap*  bitmap;
 
+    FT_UNUSED( recurse_count );
+
 
     /* check that we can write the glyph into the bitmap */
     bitmap     = decoder->bitmap;
@@ -555,8 +694,8 @@
 
     line_bits = width * decoder->bit_depth;
 
-    if ( x_pos < 0 || x_pos + width > bit_width   ||
-         y_pos < 0 || y_pos + height > bit_height )
+    if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width   ||
+         y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height )
     {
       FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:"
                   " invalid bitmap dimensions\n" ));
@@ -673,14 +812,18 @@
                                     FT_Byte*        p,
                                     FT_Byte*        limit,
                                     FT_Int          x_pos,
-                                    FT_Int          y_pos )
+                                    FT_Int          y_pos,
+                                    FT_UInt         recurse_count )
   {
     FT_Error    error = FT_Err_Ok;
     FT_Byte*    line;
-    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h, nbits;
+    FT_Int      pitch, width, height, line_bits, h, nbits;
+    FT_UInt     bit_height, bit_width;
     FT_Bitmap*  bitmap;
     FT_UShort   rval;
 
+    FT_UNUSED( recurse_count );
+
 
     /* check that we can write the glyph into the bitmap */
     bitmap     = decoder->bitmap;
@@ -694,8 +837,8 @@
 
     line_bits = width * decoder->bit_depth;
 
-    if ( x_pos < 0 || x_pos + width  > bit_width  ||
-         y_pos < 0 || y_pos + height > bit_height )
+    if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width   ||
+         y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height )
     {
       FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:"
                   " invalid bitmap dimensions\n" ));
@@ -710,6 +853,12 @@
       goto Exit;
     }
 
+    if ( !line_bits || !height )
+    {
+      /* nothing to do */
+      goto Exit;
+    }
+
     /* now do the blit */
 
     /* adjust `line' to point to the first byte of the bitmap */
@@ -749,7 +898,7 @@
         }
 
         *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) &
-                     ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );
+                     ( ~( 0xFFU << w ) << ( 8 - w - x_pos ) );
         rval     <<= 8;
 
         w = line_bits - w;
@@ -796,7 +945,8 @@
                                  FT_Byte*        p,
                                  FT_Byte*        limit,
                                  FT_Int          x_pos,
-                                 FT_Int          y_pos )
+                                 FT_Int          y_pos,
+                                 FT_UInt         recurse_count )
   {
     FT_Error  error = FT_Err_Ok;
     FT_UInt   num_components, nn;
@@ -830,8 +980,11 @@
 
 
       /* NB: a recursive call */
-      error = tt_sbit_decoder_load_image( decoder, gindex,
-                                          x_pos + dx, y_pos + dy );
+      error = tt_sbit_decoder_load_image( decoder,
+                                          gindex,
+                                          x_pos + dx,
+                                          y_pos + dy,
+                                          recurse_count + 1 );
       if ( error )
         break;
     }
@@ -863,11 +1016,14 @@
                             FT_Byte*        p,
                             FT_Byte*        limit,
                             FT_Int          x_pos,
-                            FT_Int          y_pos )
+                            FT_Int          y_pos,
+                            FT_UInt         recurse_count )
   {
     FT_Error  error = FT_Err_Ok;
     FT_ULong  png_len;
 
+    FT_UNUSED( recurse_count );
+
 
     if ( limit - p < 4 )
     {
@@ -909,7 +1065,8 @@
                                FT_ULong        glyph_start,
                                FT_ULong        glyph_size,
                                FT_Int          x_pos,
-                               FT_Int          y_pos )
+                               FT_Int          y_pos,
+                               FT_UInt         recurse_count )
   {
     FT_Error   error;
     FT_Stream  stream = decoder->stream;
@@ -919,7 +1076,8 @@
 
 
     /* seek into the EBDT table now */
-    if ( glyph_start + glyph_size > decoder->ebdt_size )
+    if ( !glyph_size                                   ||
+         glyph_start + glyph_size > decoder->ebdt_size )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -1035,7 +1193,7 @@
           goto Fail;
       }
 
-      error = loader( decoder, p, p_limit, x_pos, y_pos );
+      error = loader( decoder, p, p_limit, x_pos, y_pos, recurse_count );
     }
 
   Fail:
@@ -1050,13 +1208,9 @@
   tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
                               FT_UInt         glyph_index,
                               FT_Int          x_pos,
-                              FT_Int          y_pos )
+                              FT_Int          y_pos,
+                              FT_UInt         recurse_count )
   {
-    /*
-     *  First, we find the correct strike range that applies to this
-     *  glyph index.
-     */
-
     FT_Byte*  p          = decoder->eblc_base + decoder->strike_index_array;
     FT_Byte*  p_limit    = decoder->eblc_limit;
     FT_ULong  num_ranges = decoder->strike_index_count;
@@ -1064,6 +1218,17 @@
     FT_ULong  image_start = 0, image_end = 0, image_offset;
 
 
+    /* arbitrary recursion limit */
+    if ( recurse_count > 100 )
+    {
+      FT_TRACE4(( "tt_sbit_decoder_load_image:"
+                  " recursion depth exceeded\n" ));
+      goto Failure;
+    }
+
+
+    /* First, we find the correct strike range that applies to this */
+    /* glyph index.                                                 */
     for ( ; num_ranges > 0; num_ranges-- )
     {
       start = FT_NEXT_USHORT( p );
@@ -1148,7 +1313,8 @@
         num_glyphs = FT_NEXT_ULONG( p );
 
         /* overflow check for p + ( num_glyphs + 1 ) * 4 */
-        if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
+        if ( p + 4 > p_limit                                         ||
+             num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
           goto NoBitmap;
 
         for ( mm = 0; mm < num_glyphs; mm++ )
@@ -1227,7 +1393,8 @@
                                         image_start,
                                         image_end,
                                         x_pos,
-                                        y_pos );
+                                        y_pos,
+                                        recurse_count );
 
   Failure:
     return FT_THROW( Invalid_Table );
@@ -1260,6 +1427,8 @@
     FT_UNUSED( map );
 
 
+    strike_index = face->sbit_strike_map[strike_index];
+
     metrics->width  = 0;
     metrics->height = 0;
 
@@ -1335,6 +1504,7 @@
 
     case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ):
     case FT_MAKE_TAG( 't', 'i', 'f', 'f' ):
+    case FT_MAKE_TAG( 'r', 'g', 'b', 'l' ): /* used on iOS 7.1 */
       error = FT_THROW( Unknown_File_Format );
       break;
 
@@ -1355,9 +1525,9 @@
 
       metrics->horiBearingX = (FT_Short)originOffsetX;
       metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height );
-      metrics->horiAdvance  = (FT_Short)( aadvance *
-                                          face->root.size->metrics.x_ppem /
-                                          face->header.Units_Per_EM );
+      metrics->horiAdvance  = (FT_UShort)( aadvance *
+                                           face->root.size->metrics.x_ppem /
+                                           face->header.Units_Per_EM );
     }
 
     return error;
@@ -1389,6 +1559,7 @@
           error = tt_sbit_decoder_load_image( decoder,
                                               glyph_index,
                                               0,
+                                              0,
                                               0 );
           tt_sbit_decoder_done( decoder );
         }
@@ -1418,7 +1589,7 @@
       FT_Library  library = face->root.glyph->library;
 
 
-      FT_Bitmap_New( &new_map );
+      FT_Bitmap_Init( &new_map );
 
       /* Convert to 8bit grayscale. */
       error = FT_Bitmap_Convert( library, map, &new_map, 1 );
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index 695d0d8..d8a8167 100644
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded bitmap support (specification).       */
 /*                                                                         */
-/*  Copyright 1996-2008, 2013 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTSBIT_H__
-#define __TTSBIT_H__
+#ifndef TTSBIT_H_
+#define TTSBIT_H_
 
 
 #include <ft2build.h>
@@ -57,7 +57,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTSBIT_H__ */
+#endif /* TTSBIT_H_ */
 
 
 /* END */
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 27be966..30fd4e2 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    A new `perfect' anti-aliasing renderer (body).                       */
 /*                                                                         */
-/*  Copyright 2000-2003, 2005-2014 by                                      */
+/*  Copyright 2000-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,18 +18,18 @@
   /*************************************************************************/
   /*                                                                       */
   /* This file can be compiled without the rest of the FreeType engine, by */
-  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
+  /* defining the STANDALONE_ macro when compiling it.  You also need to   */
   /* put the files `ftgrays.h' and `ftimage.h' into the current            */
   /* compilation directory.  Typically, you could do something like        */
   /*                                                                       */
   /* - copy `src/smooth/ftgrays.c' (this file) to your current directory   */
   /*                                                                       */
-  /* - copy `include/ftimage.h' and `src/smooth/ftgrays.h' to the same     */
-  /*   directory                                                           */
+  /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
+  /*   same directory                                                      */
   /*                                                                       */
-  /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in        */
+  /* - compile `ftgrays' with the STANDALONE_ macro defined, as in         */
   /*                                                                       */
-  /*     cc -c -D_STANDALONE_ ftgrays.c                                    */
+  /*     cc -c -DSTANDALONE_ ftgrays.c                                     */
   /*                                                                       */
   /* The renderer can be initialized with a call to                        */
   /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated  */
@@ -91,7 +91,12 @@
 #define FT_COMPONENT  trace_smooth
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
+
+
+  /* The size in bytes of the render pool used by the scan-line converter  */
+  /* to do all of its work.                                                */
+#define FT_RENDER_POOL_SIZE  16384L
 
 
   /* Auxiliary macros for token concatenation. */
@@ -101,6 +106,22 @@
 #define FT_BEGIN_STMNT  do {
 #define FT_END_STMNT    } while ( 0 )
 
+#define FT_MIN( a, b )  ( (a) < (b) ? (a) : (b) )
+#define FT_MAX( a, b )  ( (a) > (b) ? (a) : (b) )
+#define FT_ABS( a )     ( (a) < 0 ? -(a) : (a) )
+
+
+  /*
+   *  Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+   *  algorithm.  We use alpha = 1, beta = 3/8, giving us results with a
+   *  largest error less than 7% compared to the exact value.
+   */
+#define FT_HYPOT( x, y )                 \
+          ( x = FT_ABS( x ),             \
+            y = FT_ABS( y ),             \
+            x > y ? x + ( 3 * y >> 3 )   \
+                  : y + ( 3 * x >> 3 ) )
+
 
   /* define this to dump debugging information */
 /* #define FT_DEBUG_LEVEL_TRACE */
@@ -115,8 +136,10 @@
 #include <string.h>
 #include <setjmp.h>
 #include <limits.h>
-#define FT_UINT_MAX  UINT_MAX
-#define FT_INT_MAX   INT_MAX
+#define FT_CHAR_BIT   CHAR_BIT
+#define FT_UINT_MAX   UINT_MAX
+#define FT_INT_MAX    INT_MAX
+#define FT_ULONG_MAX  ULONG_MAX
 
 #define ft_memset   memset
 
@@ -234,7 +257,7 @@
          };
 
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
 #include <ft2build.h>
@@ -252,7 +275,7 @@
 #define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
 
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
 #ifndef FT_MEM_SET
@@ -280,7 +303,7 @@
 
 #else /* FT_STATIC_RASTER */
 
-#define RAS_ARG   /* empty */
+#define RAS_ARG   void
 #define RAS_ARG_  /* empty */
 #define RAS_VAR   /* empty */
 #define RAS_VAR_  /* empty */
@@ -296,20 +319,19 @@
 #undef TRUNC
 #undef SCALED
 
-#define ONE_PIXEL       ( 1L << PIXEL_BITS )
-#define PIXEL_MASK      ( -1L << PIXEL_BITS )
+#define ONE_PIXEL       ( 1 << PIXEL_BITS )
 #define TRUNC( x )      ( (TCoord)( (x) >> PIXEL_BITS ) )
-#define SUBPIXELS( x )  ( (TPos)(x) << PIXEL_BITS )
+#define SUBPIXELS( x )  ( (TPos)(x) * ONE_PIXEL )
 #define FLOOR( x )      ( (x) & -ONE_PIXEL )
 #define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
 #define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
 
 #if PIXEL_BITS >= 6
-#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
+#define UPSCALE( x )    ( (x) * ( ONE_PIXEL >> 6 ) )
 #define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
 #else
 #define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
-#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x )  ( (x) * ( 64 >> PIXEL_BITS ) )
 #endif
 
 
@@ -347,6 +369,15 @@
 #endif /* __arm__ */
 
 
+  /* These macros speed up repetitive divisions by replacing them */
+  /* with multiplications and right shifts.                       */
+#define FT_UDIVPREP( b )                                       \
+  long  b ## _r = (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define FT_UDIV( a, b )                                        \
+  ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >>   \
+    ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
+
+
   /*************************************************************************/
   /*                                                                       */
   /*   TYPE DEFINITIONS                                                    */
@@ -356,44 +387,36 @@
   /* need to define them to "float" or "double" when experimenting with   */
   /* new algorithms                                                       */
 
-  typedef long  TCoord;   /* integer scanline/pixel coordinate */
   typedef long  TPos;     /* sub-pixel coordinate              */
-
-  /* determine the type used to store cell areas.  This normally takes at */
-  /* least PIXEL_BITS*2 + 1 bits.  On 16-bit systems, we need to use      */
-  /* `long' instead of `int', otherwise bad things happen                 */
-
-#if PIXEL_BITS <= 7
-
-  typedef int  TArea;
-
-#else /* PIXEL_BITS >= 8 */
-
-  /* approximately determine the size of integers using an ANSI-C header */
-#if FT_UINT_MAX == 0xFFFFU
-  typedef long  TArea;
-#else
-  typedef int   TArea;
-#endif
-
-#endif /* PIXEL_BITS >= 8 */
-
-
-  /* maximum number of gray spans in a call to the span callback */
-#define FT_MAX_GRAY_SPANS  32
+  typedef int   TCoord;   /* integer scanline/pixel coordinate */
+  typedef int   TArea;    /* cell areas, coordinate products   */
 
 
   typedef struct TCell_*  PCell;
 
   typedef struct  TCell_
   {
-    TPos    x;     /* same with gray_TWorker.ex    */
+    TCoord  x;     /* same with gray_TWorker.ex    */
     TCoord  cover; /* same with gray_TWorker.cover */
     TArea   area;
     PCell   next;
 
   } TCell;
 
+  typedef struct TPixmap_
+  {
+    unsigned char*  origin;  /* pixmap origin at the bottom-left */
+    int             pitch;   /* pitch to go down one row */
+
+  } TPixmap;
+
+  /* maximum number of gray cells in the buffer */
+#if FT_RENDER_POOL_SIZE > 2048
+#define FT_MAX_GRAY_POOL  ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) )
+#else
+#define FT_MAX_GRAY_POOL  ( 2048 / sizeof ( TCell ) )
+#endif
+
 
 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
   /* We disable the warning `structure was padded due to   */
@@ -405,10 +428,11 @@
 
   typedef struct  gray_TWorker_
   {
+    ft_jmp_buf  jump_buffer;
+
     TCoord  ex, ey;
-    TPos    min_ex, max_ex;
-    TPos    min_ey, max_ey;
-    TPos    count_ex, count_ey;
+    TCoord  min_ex, max_ex;
+    TCoord  min_ey, max_ey;
 
     TArea   area;
     TCoord  cover;
@@ -418,35 +442,15 @@
     FT_PtrDist  max_cells;
     FT_PtrDist  num_cells;
 
-    TCoord  cx, cy;
     TPos    x,  y;
 
-    TPos    last_ey;
-
-    FT_Vector   bez_stack[32 * 3 + 1];
-    int         lev_stack[32];
-
     FT_Outline  outline;
-    FT_Bitmap   target;
-    FT_BBox     clip_box;
-
-    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
-    int         num_gray_spans;
+    TPixmap     target;
 
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
-    int                  span_y;
-
-    int  band_size;
-    int  band_shoot;
-
-    ft_jmp_buf  jump_buffer;
-
-    void*       buffer;
-    long        buffer_size;
 
     PCell*     ycells;
-    TPos       ycount;
 
   } gray_TWorker, *gray_PWorker;
 
@@ -464,79 +468,36 @@
 
   typedef struct gray_TRaster_
   {
-    void*         buffer;
-    long          buffer_size;
-    int           band_size;
     void*         memory;
-    gray_PWorker  worker;
 
   } gray_TRaster, *gray_PRaster;
 
 
+#ifdef FT_DEBUG_LEVEL_TRACE
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* Initialize the cells table.                                           */
-  /*                                                                       */
+  /* to be called while in the debugger --                                */
+  /* this function causes a compiler warning since it is unused otherwise */
   static void
-  gray_init_cells( RAS_ARG_ void*  buffer,
-                   long            byte_size )
+  gray_dump_cells( RAS_ARG )
   {
-    ras.buffer      = buffer;
-    ras.buffer_size = byte_size;
+    int  y;
 
-    ras.ycells      = (PCell*) buffer;
-    ras.cells       = NULL;
-    ras.max_cells   = 0;
-    ras.num_cells   = 0;
-    ras.area        = 0;
-    ras.cover       = 0;
-    ras.invalid     = 1;
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell  cell = ras.ycells[y - ras.min_ey];
+
+
+      printf( "%3d:", y );
+
+      for ( ; cell != NULL; cell = cell->next )
+        printf( " (%3d, c:%4d, a:%6d)",
+                cell->x, cell->cover, cell->area );
+      printf( "\n" );
+    }
   }
 
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Compute the outline bounding box.                                     */
-  /*                                                                       */
-  static void
-  gray_compute_cbox( RAS_ARG )
-  {
-    FT_Outline*  outline = &ras.outline;
-    FT_Vector*   vec     = outline->points;
-    FT_Vector*   limit   = vec + outline->n_points;
-
-
-    if ( outline->n_points <= 0 )
-    {
-      ras.min_ex = ras.max_ex = 0;
-      ras.min_ey = ras.max_ey = 0;
-      return;
-    }
-
-    ras.min_ex = ras.max_ex = vec->x;
-    ras.min_ey = ras.max_ey = vec->y;
-
-    vec++;
-
-    for ( ; vec < limit; vec++ )
-    {
-      TPos  x = vec->x;
-      TPos  y = vec->y;
-
-
-      if ( x < ras.min_ex ) ras.min_ex = x;
-      if ( x > ras.max_ex ) ras.max_ex = x;
-      if ( y < ras.min_ey ) ras.min_ey = y;
-      if ( y > ras.max_ey ) ras.max_ey = y;
-    }
-
-    /* truncate the bounding box to integer pixels */
-    ras.min_ex = ras.min_ex >> 6;
-    ras.min_ey = ras.min_ey >> 6;
-    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
-    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
-  }
+#endif /* FT_DEBUG_LEVEL_TRACE */
 
 
   /*************************************************************************/
@@ -547,13 +508,10 @@
   gray_find_cell( RAS_ARG )
   {
     PCell  *pcell, cell;
-    TPos    x = ras.ex;
+    TCoord  x = ras.ex;
 
 
-    if ( x > ras.count_ex )
-      x = ras.count_ex;
-
-    pcell = &ras.ycells[ras.ey];
+    pcell = &ras.ycells[ras.ey - ras.min_ey];
     for (;;)
     {
       cell = *pcell;
@@ -616,58 +574,26 @@
 
     /* All cells that are on the left of the clipping region go to the */
     /* min_ex - 1 horizontal position.                                 */
-    ey -= ras.min_ey;
-
-    if ( ex > ras.max_ex )
-      ex = ras.max_ex;
-
-    ex -= ras.min_ex;
-    if ( ex < 0 )
-      ex = -1;
-
-    /* are we moving to a different cell ? */
-    if ( ex != ras.ex || ey != ras.ey )
-    {
-      /* record the current one if it is valid */
-      if ( !ras.invalid )
-        gray_record_cell( RAS_VAR );
-
-      ras.area  = 0;
-      ras.cover = 0;
-      ras.ex    = ex;
-      ras.ey    = ey;
-    }
-
-    ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
-                              ex >= ras.count_ex           );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Start a new contour at a given cell.                                  */
-  /*                                                                       */
-  static void
-  gray_start_cell( RAS_ARG_ TCoord  ex,
-                            TCoord  ey )
-  {
-    if ( ex > ras.max_ex )
-      ex = (TCoord)( ras.max_ex );
 
     if ( ex < ras.min_ex )
-      ex = (TCoord)( ras.min_ex - 1 );
+      ex = ras.min_ex - 1;
 
-    ras.area    = 0;
-    ras.cover   = 0;
-    ras.ex      = ex - ras.min_ex;
-    ras.ey      = ey - ras.min_ey;
-    ras.last_ey = SUBPIXELS( ey );
-    ras.invalid = 0;
+    /* record the current one if it is valid */
+    if ( !ras.invalid )
+      gray_record_cell( RAS_VAR );
 
-    gray_set_cell( RAS_VAR_ ex, ey );
+    ras.area  = 0;
+    ras.cover = 0;
+    ras.ex    = ex;
+    ras.ey    = ey;
+
+    ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
+                    ex >= ras.max_ex );
   }
 
 
+#ifndef FT_LONG64
+
   /*************************************************************************/
   /*                                                                       */
   /* Render a scanline as one or more cells.                               */
@@ -679,17 +605,13 @@
                                  TPos    x2,
                                  TCoord  y2 )
   {
-    TCoord  ex1, ex2, fx1, fx2, delta, mod;
-    long    p, first, dx;
+    TCoord  ex1, ex2, fx1, fx2, first, delta, mod;
+    TPos    p, dx;
     int     incr;
 
 
-    dx = x2 - x1;
-
     ex1 = TRUNC( x1 );
     ex2 = TRUNC( x2 );
-    fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
-    fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
 
     /* trivial case.  Happens often */
     if ( y1 == y2 )
@@ -698,11 +620,14 @@
       return;
     }
 
+    fx1   = (TCoord)( x1 - SUBPIXELS( ex1 ) );
+    fx2   = (TCoord)( x2 - SUBPIXELS( ex2 ) );
+    delta = y2 - y1;
+
     /* everything is located in a single cell.  That is easy! */
     /*                                                        */
     if ( ex1 == ex2 )
     {
-      delta      = y2 - y1;
       ras.area  += (TArea)(( fx1 + fx2 ) * delta);
       ras.cover += delta;
       return;
@@ -711,13 +636,17 @@
     /* ok, we'll have to render a run of adjacent cells on the same */
     /* scanline...                                                  */
     /*                                                              */
-    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
-    first = ONE_PIXEL;
-    incr  = 1;
+    dx = x2 - x1;
 
-    if ( dx < 0 )
+    if ( dx > 0 )
     {
-      p     = fx1 * ( y2 - y1 );
+      p     = ( ONE_PIXEL - fx1 ) * delta;
+      first = ONE_PIXEL;
+      incr  = 1;
+    }
+    else
+    {
+      p     = fx1 * delta;
       first = 0;
       incr  = -1;
       dx    = -dx;
@@ -742,7 +671,7 @@
 
       mod -= (int)dx;
 
-      while ( ex1 != ex2 )
+      do
       {
         delta = lift;
         mod  += rem;
@@ -757,7 +686,7 @@
         y1        += delta;
         ex1       += incr;
         gray_set_cell( RAS_VAR_ ex1, ey );
-      }
+      } while ( ex1 != ex2 );
     }
 
     delta      = y2 - y1;
@@ -774,35 +703,21 @@
   gray_render_line( RAS_ARG_ TPos  to_x,
                              TPos  to_y )
   {
-    TCoord  ey1, ey2, fy1, fy2, mod;
-    TPos    dx, dy, x, x2;
-    long    p, first;
-    int     delta, rem, lift, incr;
+    TCoord  ey1, ey2, fy1, fy2, first, delta, mod;
+    TPos    p, dx, dy, x, x2;
+    int     incr;
 
 
-    ey1 = TRUNC( ras.last_ey );
+    ey1 = TRUNC( ras.y );
     ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
-    fy1 = (TCoord)( ras.y - ras.last_ey );
-    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
-
-    dx = to_x - ras.x;
-    dy = to_y - ras.y;
 
     /* perform vertical clipping */
-    {
-      TCoord  min, max;
+    if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+         ( ey1 <  ras.min_ey && ey2 <  ras.min_ey ) )
+      goto End;
 
-
-      min = ey1;
-      max = ey2;
-      if ( ey1 > ey2 )
-      {
-        min = ey2;
-        max = ey1;
-      }
-      if ( min >= ras.max_ey || max < ras.min_ey )
-        goto End;
-    }
+    fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
+    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
 
     /* everything is on a single scanline */
     if ( ey1 == ey2 )
@@ -811,9 +726,10 @@
       goto End;
     }
 
-    /* vertical line - avoid calling gray_render_scanline */
-    incr = 1;
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
 
+    /* vertical line - avoid calling gray_render_scanline */
     if ( dx == 0 )
     {
       TCoord  ex     = TRUNC( ras.x );
@@ -821,21 +737,25 @@
       TArea   area;
 
 
-      first = ONE_PIXEL;
-      if ( dy < 0 )
+      if ( dy > 0)
+      {
+        first = ONE_PIXEL;
+        incr  = 1;
+      }
+      else
       {
         first = 0;
         incr  = -1;
       }
 
-      delta      = (int)( first - fy1 );
+      delta      = first - fy1;
       ras.area  += (TArea)two_fx * delta;
       ras.cover += delta;
       ey1       += incr;
 
       gray_set_cell( RAS_VAR_ ex, ey1 );
 
-      delta = (int)( first + first - ONE_PIXEL );
+      delta = first + first - ONE_PIXEL;
       area  = (TArea)two_fx * delta;
       while ( ey1 != ey2 )
       {
@@ -846,7 +766,7 @@
         gray_set_cell( RAS_VAR_ ex, ey1 );
       }
 
-      delta      = (int)( fy2 - ONE_PIXEL + first );
+      delta      = fy2 - ONE_PIXEL + first;
       ras.area  += (TArea)two_fx * delta;
       ras.cover += delta;
 
@@ -854,11 +774,13 @@
     }
 
     /* ok, we have to render several scanlines */
-    p     = ( ONE_PIXEL - fy1 ) * dx;
-    first = ONE_PIXEL;
-    incr  = 1;
-
-    if ( dy < 0 )
+    if ( dy > 0)
+    {
+      p     = ( ONE_PIXEL - fy1 ) * dx;
+      first = ONE_PIXEL;
+      incr  = 1;
+    }
+    else
     {
       p     = fy1 * dx;
       first = 0;
@@ -866,51 +788,191 @@
       dy    = -dy;
     }
 
-    FT_DIV_MOD( int, p, dy, delta, mod );
+    FT_DIV_MOD( TCoord, p, dy, delta, mod );
 
     x = ras.x + delta;
-    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
+    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
 
     ey1 += incr;
     gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
 
     if ( ey1 != ey2 )
     {
-      p     = ONE_PIXEL * dx;
-      FT_DIV_MOD( int, p, dy, lift, rem );
-      mod -= (int)dy;
+      TCoord  lift, rem;
 
-      while ( ey1 != ey2 )
+
+      p    = ONE_PIXEL * dx;
+      FT_DIV_MOD( TCoord, p, dy, lift, rem );
+      mod -= (TCoord)dy;
+
+      do
       {
         delta = lift;
         mod  += rem;
         if ( mod >= 0 )
         {
-          mod -= (int)dy;
+          mod -= (TCoord)dy;
           delta++;
         }
 
         x2 = x + delta;
-        gray_render_scanline( RAS_VAR_ ey1, x,
-                                       (TCoord)( ONE_PIXEL - first ), x2,
-                                       (TCoord)first );
+        gray_render_scanline( RAS_VAR_ ey1,
+                                       x, ONE_PIXEL - first,
+                                       x2, first );
         x = x2;
 
         ey1 += incr;
         gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
-      }
+      } while ( ey1 != ey2 );
     }
 
-    gray_render_scanline( RAS_VAR_ ey1, x,
-                                   (TCoord)( ONE_PIXEL - first ), to_x,
-                                   fy2 );
+    gray_render_scanline( RAS_VAR_ ey1,
+                                   x, ONE_PIXEL - first,
+                                   to_x, fy2 );
 
   End:
     ras.x       = to_x;
     ras.y       = to_y;
-    ras.last_ey = SUBPIXELS( ey2 );
   }
 
+#else
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Render a straight line across multiple cells in any direction.        */
+  /*                                                                       */
+  static void
+  gray_render_line( RAS_ARG_ TPos  to_x,
+                             TPos  to_y )
+  {
+    TPos    dx, dy, fx1, fy1, fx2, fy2;
+    TCoord  ex1, ex2, ey1, ey2;
+
+
+    ey1 = TRUNC( ras.y );
+    ey2 = TRUNC( to_y );
+
+    /* perform vertical clipping */
+    if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+         ( ey1 <  ras.min_ey && ey2 <  ras.min_ey ) )
+      goto End;
+
+    ex1 = TRUNC( ras.x );
+    ex2 = TRUNC( to_x );
+
+    fx1 = ras.x - SUBPIXELS( ex1 );
+    fy1 = ras.y - SUBPIXELS( ey1 );
+
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
+
+    if ( ex1 == ex2 && ey1 == ey2 )       /* inside one cell */
+      ;
+    else if ( dy == 0 ) /* ex1 != ex2 */  /* any horizontal line */
+    {
+      ex1 = ex2;
+      gray_set_cell( RAS_VAR_ ex1, ey1 );
+    }
+    else if ( dx == 0 )
+    {
+      if ( dy > 0 )                       /* vertical line up */
+        do
+        {
+          fy2 = ONE_PIXEL;
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * fx1 * 2;
+          fy1 = 0;
+          ey1++;
+          gray_set_cell( RAS_VAR_ ex1, ey1 );
+        } while ( ey1 != ey2 );
+      else                                /* vertical line down */
+        do
+        {
+          fy2 = 0;
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * fx1 * 2;
+          fy1 = ONE_PIXEL;
+          ey1--;
+          gray_set_cell( RAS_VAR_ ex1, ey1 );
+        } while ( ey1 != ey2 );
+    }
+    else                                  /* any other line */
+    {
+      TPos  prod = dx * fy1 - dy * fx1;
+      FT_UDIVPREP( dx );
+      FT_UDIVPREP( dy );
+
+
+      /* The fundamental value `prod' determines which side and the  */
+      /* exact coordinate where the line exits current cell.  It is  */
+      /* also easily updated when moving from one cell to the next.  */
+      do
+      {
+        if      ( prod                                   <= 0 &&
+                  prod - dx * ONE_PIXEL                  >  0 ) /* left */
+        {
+          fx2 = 0;
+          fy2 = (TPos)FT_UDIV( -prod, -dx );
+          prod -= dy * ONE_PIXEL;
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          fx1 = ONE_PIXEL;
+          fy1 = fy2;
+          ex1--;
+        }
+        else if ( prod - dx * ONE_PIXEL                  <= 0 &&
+                  prod - dx * ONE_PIXEL + dy * ONE_PIXEL >  0 ) /* up */
+        {
+          prod -= dx * ONE_PIXEL;
+          fx2 = (TPos)FT_UDIV( -prod, dy );
+          fy2 = ONE_PIXEL;
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          fx1 = fx2;
+          fy1 = 0;
+          ey1++;
+        }
+        else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
+                  prod                  + dy * ONE_PIXEL >= 0 ) /* right */
+        {
+          prod += dy * ONE_PIXEL;
+          fx2 = ONE_PIXEL;
+          fy2 = (TPos)FT_UDIV( prod, dx );
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          fx1 = 0;
+          fy1 = fy2;
+          ex1++;
+        }
+        else /* ( prod                  + dy * ONE_PIXEL <  0 &&
+                  prod                                   >  0 )    down */
+        {
+          fx2 = (TPos)FT_UDIV( prod, -dy );
+          fy2 = 0;
+          prod += dx * ONE_PIXEL;
+          ras.cover += ( fy2 - fy1 );
+          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          fx1 = fx2;
+          fy1 = ONE_PIXEL;
+          ey1--;
+        }
+
+        gray_set_cell( RAS_VAR_ ex1, ey1 );
+      } while ( ex1 != ex2 || ey1 != ey2 );
+    }
+
+    fx2 = to_x - SUBPIXELS( ex2 );
+    fy2 = to_y - SUBPIXELS( ey2 );
+
+    ras.cover += ( fy2 - fy1 );
+    ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+
+  End:
+    ras.x       = to_x;
+    ras.y       = to_y;
+  }
+
+#endif
 
   static void
   gray_split_conic( FT_Vector*  base )
@@ -936,73 +998,64 @@
   gray_render_conic( RAS_ARG_ const FT_Vector*  control,
                               const FT_Vector*  to )
   {
+    FT_Vector   bez_stack[16 * 2 + 1];  /* enough to accommodate bisections */
+    FT_Vector*  arc = bez_stack;
     TPos        dx, dy;
-    TPos        min, max, y;
-    int         top, level;
-    int*        levels;
-    FT_Vector*  arc;
+    int         draw, split;
 
 
-    levels = ras.lev_stack;
-
-    arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[1].x = UPSCALE( control->x );
     arc[1].y = UPSCALE( control->y );
     arc[2].x = ras.x;
     arc[2].y = ras.y;
-    top      = 0;
+
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+           TRUNC( arc[1].y ) >= ras.max_ey &&
+           TRUNC( arc[2].y ) >= ras.max_ey ) ||
+         ( TRUNC( arc[0].y ) <  ras.min_ey &&
+           TRUNC( arc[1].y ) <  ras.min_ey &&
+           TRUNC( arc[2].y ) <  ras.min_ey ) )
+    {
+      ras.x = arc[0].x;
+      ras.y = arc[0].y;
+      return;
+    }
 
     dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
     dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
     if ( dx < dy )
       dx = dy;
 
-    if ( dx < ONE_PIXEL / 4 )
-      goto Draw;
+    /* We can calculate the number of necessary bisections because  */
+    /* each bisection predictably reduces deviation exactly 4-fold. */
+    /* Even 32-bit deviation would vanish after 16 bisections.      */
+    draw = 1;
+    while ( dx > ONE_PIXEL / 4 )
+    {
+      dx   >>= 2;
+      draw <<= 1;
+    }
 
-    /* short-cut the arc that crosses the current band */
-    min = max = arc[0].y;
-
-    y = arc[1].y;
-    if ( y < min ) min = y;
-    if ( y > max ) max = y;
-
-    y = arc[2].y;
-    if ( y < min ) min = y;
-    if ( y > max ) max = y;
-
-    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
-      goto Draw;
-
-    level = 0;
+    /* We use decrement counter to count the total number of segments */
+    /* to draw starting from 2^level. Before each draw we split as    */
+    /* many times as there are trailing zeros in the counter.         */
     do
     {
-      dx >>= 2;
-      level++;
-    } while ( dx > ONE_PIXEL / 4 );
-
-    levels[0] = level;
-
-    do
-    {
-      level = levels[top];
-      if ( level > 0 )
+      split = 1;
+      while ( ( draw & split ) == 0 )
       {
         gray_split_conic( arc );
         arc += 2;
-        top++;
-        levels[top] = levels[top - 1] = level - 1;
-        continue;
+        split <<= 1;
       }
 
-    Draw:
       gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
-      top--;
       arc -= 2;
 
-    } while ( top >= 0 );
+    } while ( --draw );
   }
 
 
@@ -1039,11 +1092,13 @@
                               const FT_Vector*  control2,
                               const FT_Vector*  to )
   {
-    FT_Vector*  arc;
-    TPos        min, max, y;
+    FT_Vector   bez_stack[16 * 3 + 1];  /* enough to accommodate bisections */
+    FT_Vector*  arc = bez_stack;
+    TPos        dx, dy, dx_, dy_;
+    TPos        dx1, dy1, dx2, dy2;
+    TPos        L, s, s_limit;
 
 
-    arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[1].x = UPSCALE( control2->x );
@@ -1053,29 +1108,20 @@
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    /* Short-cut the arc that crosses the current band. */
-    min = max = arc[0].y;
-
-    y = arc[1].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    y = arc[2].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    y = arc[3].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
-      goto Draw;
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+           TRUNC( arc[1].y ) >= ras.max_ey &&
+           TRUNC( arc[2].y ) >= ras.max_ey &&
+           TRUNC( arc[3].y ) >= ras.max_ey ) ||
+         ( TRUNC( arc[0].y ) <  ras.min_ey &&
+           TRUNC( arc[1].y ) <  ras.min_ey &&
+           TRUNC( arc[2].y ) <  ras.min_ey &&
+           TRUNC( arc[3].y ) <  ras.min_ey ) )
+    {
+      ras.x = arc[0].x;
+      ras.y = arc[0].y;
+      return;
+    }
 
     for (;;)
     {
@@ -1084,91 +1130,53 @@
       /* F. Hain, at                                                      */
       /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
 
-      {
-        TPos  dx, dy, dx_, dy_;
-        TPos  dx1, dy1, dx2, dy2;
-        TPos  L, s, s_limit;
+      /* dx and dy are x and y components of the P0-P3 chord vector. */
+      dx = dx_ = arc[3].x - arc[0].x;
+      dy = dy_ = arc[3].y - arc[0].y;
 
+      L = FT_HYPOT( dx_, dy_ );
 
-        /* dx and dy are x and y components of the P0-P3 chord vector. */
-        dx = arc[3].x - arc[0].x;
-        dy = arc[3].y - arc[0].y;
+      /* Avoid possible arithmetic overflow below by splitting. */
+      if ( L > 32767 )
+        goto Split;
 
-        /* L is an (under)estimate of the Euclidean distance P0-P3.       */
-        /*                                                                */
-        /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated   */
-        /* with least maximum error by                                    */
-        /*                                                                */
-        /*   r_upperbound = dx + (sqrt(2) - 1) * dy  ,                    */
-        /*                                                                */
-        /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
-        /* error of no more than 8.4%.                                    */
-        /*                                                                */
-        /* Similarly, some elementary calculus shows that r can be        */
-        /* underestimated with least maximum error by                     */
-        /*                                                                */
-        /*   r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx                    */
-        /*                  + sqrt(2 - sqrt(2)) / 2 * dy  .               */
-        /*                                                                */
-        /* 236/256 and 97/256 are (under)estimates of the two algebraic   */
-        /* numbers, giving an error of no more than 8.1%.                 */
+      /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+      s_limit = L * (TPos)( ONE_PIXEL / 6 );
 
-        dx_ = FT_ABS( dx );
-        dy_ = FT_ABS( dy );
+      /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+      dx1 = arc[1].x - arc[0].x;
+      dy1 = arc[1].y - arc[0].y;
+      s = FT_ABS( dy * dx1 - dx * dy1 );
 
-        /* This is the same as                     */
-        /*                                         */
-        /*   L = ( 236 * FT_MAX( dx_, dy_ )        */
-        /*       + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
-        L = ( dx_ > dy_ ? 236 * dx_ +  97 * dy_
-                        :  97 * dx_ + 236 * dy_ ) >> 8;
+      if ( s > s_limit )
+        goto Split;
 
-        /* Avoid possible arithmetic overflow below by splitting. */
-        if ( L > 32767 )
-          goto Split;
+      /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+      dx2 = arc[2].x - arc[0].x;
+      dy2 = arc[2].y - arc[0].y;
+      s = FT_ABS( dy * dx2 - dx * dy2 );
 
-        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
-        s_limit = L * (TPos)( ONE_PIXEL / 6 );
+      if ( s > s_limit )
+        goto Split;
 
-        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
-        dx1 = arc[1].x - arc[0].x;
-        dy1 = arc[1].y - arc[0].y;
-        s = FT_ABS( dy * dx1 - dx * dy1 );
+      /* Split super curvy segments where the off points are so far
+         from the chord that the angles P0-P1-P3 or P0-P2-P3 become
+         acute as detected by appropriate dot products. */
+      if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
+           dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
+        goto Split;
 
-        if ( s > s_limit )
-          goto Split;
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
 
-        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
-        dx2 = arc[2].x - arc[0].x;
-        dy2 = arc[2].y - arc[0].y;
-        s = FT_ABS( dy * dx2 - dx * dy2 );
+      if ( arc == bez_stack )
+        return;
 
-        if ( s > s_limit )
-          goto Split;
-
-        /* Split super curvy segments where the off points are so far
-           from the chord that the angles P0-P1-P3 or P0-P2-P3 become
-           acute as detected by appropriate dot products. */
-        if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
-             dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
-          goto Split;
-
-        /* No reason to split. */
-        goto Draw;
-      }
+      arc -= 3;
+      continue;
 
     Split:
       gray_split_cubic( arc );
       arc += 3;
-      continue;
-
-    Draw:
-      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
-
-      if ( arc == ras.bez_stack )
-        return;
-
-      arc -= 3;
     }
   }
 
@@ -1180,18 +1188,14 @@
     TPos  x, y;
 
 
-    /* record current cell, if any */
-    if ( !ras.invalid )
-      gray_record_cell( RAS_VAR );
-
     /* start to a new position */
     x = UPSCALE( to->x );
     y = UPSCALE( to->y );
 
-    gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
+    gray_set_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
 
-    worker->x = x;
-    worker->y = y;
+    ras.x = x;
+    ras.y = y;
     return 0;
   }
 
@@ -1227,63 +1231,13 @@
 
 
   static void
-  gray_render_span( int             y,
-                    int             count,
-                    const FT_Span*  spans,
-                    gray_PWorker    worker )
-  {
-    unsigned char*  p;
-    FT_Bitmap*      map = &worker->target;
-
-
-    /* first of all, compute the scanline offset */
-    p = (unsigned char*)map->buffer - y * map->pitch;
-    if ( map->pitch >= 0 )
-      p += (unsigned)( ( map->rows - 1 ) * map->pitch );
-
-    for ( ; count > 0; count--, spans++ )
-    {
-      unsigned char  coverage = spans->coverage;
-
-
-      if ( coverage )
-      {
-        /* For small-spans it is faster to do it by ourselves than
-         * calling `memset'.  This is mainly due to the cost of the
-         * function call.
-         */
-        if ( spans->len >= 8 )
-          FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
-        else
-        {
-          unsigned char*  q = p + spans->x;
-
-
-          switch ( spans->len )
-          {
-          case 7: *q++ = (unsigned char)coverage;
-          case 6: *q++ = (unsigned char)coverage;
-          case 5: *q++ = (unsigned char)coverage;
-          case 4: *q++ = (unsigned char)coverage;
-          case 3: *q++ = (unsigned char)coverage;
-          case 2: *q++ = (unsigned char)coverage;
-          case 1: *q   = (unsigned char)coverage;
-          default:
-            ;
-          }
-        }
-      }
-    }
-  }
-
-
-  static void
   gray_hline( RAS_ARG_ TCoord  x,
                        TCoord  y,
-                       TPos    area,
+                       TArea   area,
                        TCoord  acount )
   {
-    int  coverage;
+    int      coverage;
+    FT_Span  span;
 
 
     /* compute the coverage line's coverage, depending on the    */
@@ -1312,179 +1266,91 @@
         coverage = 255;
     }
 
-    y += (TCoord)ras.min_ey;
-    x += (TCoord)ras.min_ex;
-
-    /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
-    if ( x >= 32767 )
-      x = 32767;
-
-    /* FT_Span.y is an integer, so limit our coordinates appropriately */
-    if ( y >= FT_INT_MAX )
-      y = FT_INT_MAX;
-
-    if ( coverage )
+    if ( ras.render_span )  /* for FT_RASTER_FLAG_DIRECT only */
     {
-      FT_Span*  span;
-      int       count;
+      span.x        = (short)x;
+      span.len      = (unsigned short)acount;
+      span.coverage = (unsigned char)coverage;
+
+      ras.render_span( y, 1, &span, ras.render_span_data );
+    }
+    else
+    {
+      unsigned char*  q = ras.target.origin - ras.target.pitch * y + x;
+      unsigned char   c = (unsigned char)coverage;
 
 
-      /* see whether we can add this span to the current list */
-      count = ras.num_gray_spans;
-      span  = ras.gray_spans + count - 1;
-      if ( count > 0                          &&
-           ras.span_y == y                    &&
-           (int)span->x + span->len == (int)x &&
-           span->coverage == coverage         )
+      /* For small-spans it is faster to do it by ourselves than
+       * calling `memset'.  This is mainly due to the cost of the
+       * function call.
+       */
+      switch ( acount )
       {
-        span->len = (unsigned short)( span->len + acount );
-        return;
+      case 7: *q++ = c;
+      case 6: *q++ = c;
+      case 5: *q++ = c;
+      case 4: *q++ = c;
+      case 3: *q++ = c;
+      case 2: *q++ = c;
+      case 1: *q   = c;
+      case 0: break;
+      default:
+        FT_MEM_SET( q, c, acount );
       }
-
-      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
-      {
-        if ( ras.render_span && count > 0 )
-          ras.render_span( ras.span_y, count, ras.gray_spans,
-                           ras.render_span_data );
-
-#ifdef FT_DEBUG_LEVEL_TRACE
-
-        if ( count > 0 )
-        {
-          int  n;
-
-
-          FT_TRACE7(( "y = %3d ", ras.span_y ));
-          span = ras.gray_spans;
-          for ( n = 0; n < count; n++, span++ )
-            FT_TRACE7(( "[%d..%d]:%02x ",
-                        span->x, span->x + span->len - 1, span->coverage ));
-          FT_TRACE7(( "\n" ));
-        }
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
-        ras.num_gray_spans = 0;
-        ras.span_y         = (int)y;
-
-        span  = ras.gray_spans;
-      }
-      else
-        span++;
-
-      /* add a gray span to the current list */
-      span->x        = (short)x;
-      span->len      = (unsigned short)acount;
-      span->coverage = (unsigned char)coverage;
-
-      ras.num_gray_spans++;
     }
   }
 
 
-#ifdef FT_DEBUG_LEVEL_TRACE
-
-  /* to be called while in the debugger --                                */
-  /* this function causes a compiler warning since it is unused otherwise */
   static void
-  gray_dump_cells( RAS_ARG )
+  gray_sweep( RAS_ARG )
   {
-    int  yindex;
-
-
-    for ( yindex = 0; yindex < ras.ycount; yindex++ )
-    {
-      PCell  cell;
-
-
-      printf( "%3d:", yindex );
-
-      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
-        printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
-      printf( "\n" );
-    }
-  }
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
-
-  static void
-  gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
-  {
-    int  yindex;
-
-    FT_UNUSED( target );
+    int  y;
 
 
     if ( ras.num_cells == 0 )
       return;
 
-    ras.num_gray_spans = 0;
-
     FT_TRACE7(( "gray_sweep: start\n" ));
 
-    for ( yindex = 0; yindex < ras.ycount; yindex++ )
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
     {
-      PCell   cell  = ras.ycells[yindex];
+      PCell   cell  = ras.ycells[y - ras.min_ey];
       TCoord  cover = 0;
-      TCoord  x     = 0;
+      TCoord  x     = ras.min_ex;
 
 
       for ( ; cell != NULL; cell = cell->next )
       {
-        TPos  area;
+        TArea  area;
 
 
-        if ( cell->x > x && cover != 0 )
-          gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
+        if ( cover != 0 && cell->x > x )
+          gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ),
                       cell->x - x );
 
         cover += cell->cover;
-        area   = cover * ( ONE_PIXEL * 2 ) - cell->area;
+        area   = (TArea)cover * ( ONE_PIXEL * 2 ) - cell->area;
 
-        if ( area != 0 && cell->x >= 0 )
-          gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
+        if ( area != 0 && cell->x >= ras.min_ex )
+          gray_hline( RAS_VAR_ cell->x, y, area, 1 );
 
         x = cell->x + 1;
       }
 
       if ( cover != 0 )
-        gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
-                    ras.count_ex - x );
-    }
-
-    if ( ras.render_span && ras.num_gray_spans > 0 )
-      ras.render_span( ras.span_y, ras.num_gray_spans,
-                       ras.gray_spans, ras.render_span_data );
-
-#ifdef FT_DEBUG_LEVEL_TRACE
-
-    if ( ras.num_gray_spans > 0 )
-    {
-      FT_Span*  span;
-      int       n;
-
-
-      FT_TRACE7(( "y = %3d ", ras.span_y ));
-      span = ras.gray_spans;
-      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
-        FT_TRACE7(( "[%d..%d]:%02x ",
-                    span->x, span->x + span->len - 1, span->coverage ));
-      FT_TRACE7(( "\n" ));
+        gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ),
+                    ras.max_ex - x );
     }
 
     FT_TRACE7(( "gray_sweep: end\n" ));
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
   }
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
   /*************************************************************************/
   /*                                                                       */
-  /*  The following function should only compile in stand-alone mode,      */
+  /*  The following functions should only compile in stand-alone mode,     */
   /*  i.e., when building this component without the rest of FreeType.     */
   /*                                                                       */
   /*************************************************************************/
@@ -1542,7 +1408,10 @@
     TPos  delta;
 
 
-    if ( !outline || !func_interface )
+    if ( !outline )
+      return FT_THROW( Invalid_Outline );
+
+    if ( !func_interface )
       return FT_THROW( Invalid_Argument );
 
     shift = func_interface->shift;
@@ -1759,23 +1628,94 @@
     return FT_THROW( Invalid_Outline );
   }
 
-#endif /* _STANDALONE_ */
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_CBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Return an outline's `control box'.  The control box encloses all   */
+  /*    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  */
+  /*    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.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acbox   :: The outline's control box.                              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    See @FT_Glyph_Get_CBox for a discussion of tricky fonts.           */
+  /*                                                                       */
 
-  typedef struct  gray_TBand_
+  static void
+  FT_Outline_Get_CBox( const FT_Outline*  outline,
+                       FT_BBox           *acbox )
   {
-    TPos  min, max;
+    TPos  xMin, yMin, xMax, yMax;
 
-  } gray_TBand;
 
-    FT_DEFINE_OUTLINE_FUNCS(func_interface,
-      (FT_Outline_MoveTo_Func) gray_move_to,
-      (FT_Outline_LineTo_Func) gray_line_to,
-      (FT_Outline_ConicTo_Func)gray_conic_to,
-      (FT_Outline_CubicTo_Func)gray_cubic_to,
-      0,
-      0
-    )
+    if ( outline && acbox )
+    {
+      if ( outline->n_points == 0 )
+      {
+        xMin = 0;
+        yMin = 0;
+        xMax = 0;
+        yMax = 0;
+      }
+      else
+      {
+        FT_Vector*  vec   = outline->points;
+        FT_Vector*  limit = vec + outline->n_points;
+
+
+        xMin = xMax = vec->x;
+        yMin = yMax = vec->y;
+        vec++;
+
+        for ( ; vec < limit; vec++ )
+        {
+          TPos  x, y;
+
+
+          x = vec->x;
+          if ( x < xMin ) xMin = x;
+          if ( x > xMax ) xMax = x;
+
+          y = vec->y;
+          if ( y < yMin ) yMin = y;
+          if ( y > yMax ) yMax = y;
+        }
+      }
+      acbox->xMin = xMin;
+      acbox->xMax = xMax;
+      acbox->yMin = yMin;
+      acbox->yMax = yMax;
+    }
+  }
+
+#endif /* STANDALONE_ */
+
+
+  FT_DEFINE_OUTLINE_FUNCS(
+    func_interface,
+
+    (FT_Outline_MoveTo_Func) gray_move_to,
+    (FT_Outline_LineTo_Func) gray_line_to,
+    (FT_Outline_ConicTo_Func)gray_conic_to,
+    (FT_Outline_CubicTo_Func)gray_cubic_to,
+    0,
+    0 )
+
 
   static int
   gray_convert_glyph_inner( RAS_ARG )
@@ -1793,10 +1733,18 @@
       error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
       if ( !ras.invalid )
         gray_record_cell( RAS_VAR );
+
+      FT_TRACE7(( "band [%d..%d]: %d cells\n",
+                  ras.min_ey, ras.max_ey, ras.num_cells ));
     }
     else
+    {
       error = FT_THROW( Memory_Overflow );
 
+      FT_TRACE7(( "band [%d..%d]: to be bisected\n",
+                  ras.min_ey, ras.max_ey ));
+    }
+
     return error;
   }
 
@@ -1804,100 +1752,72 @@
   static int
   gray_convert_glyph( RAS_ARG )
   {
-    gray_TBand            bands[40];
-    gray_TBand* volatile  band;
-    int volatile          n, num_bands;
-    TPos volatile         min, max, max_y;
-    FT_BBox*              clip;
+    TCell    buffer[FT_MAX_GRAY_POOL];
+    TCoord   band_size = FT_MAX_GRAY_POOL / 8;
+    TCoord   count = ras.max_ey - ras.min_ey;
+    int      num_bands;
+    TCoord   min, max, max_y;
+    TCoord   bands[32];  /* enough to accommodate bisections */
+    TCoord*  band;
 
 
-    /* Set up state in the raster object */
-    gray_compute_cbox( RAS_VAR );
-
-    /* clip to target bitmap, exit if nothing to do */
-    clip = &ras.clip_box;
-
-    if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
-         ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
-      return 0;
-
-    if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
-    if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
-
-    if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
-    if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
-
-    ras.count_ex = ras.max_ex - ras.min_ex;
-    ras.count_ey = ras.max_ey - ras.min_ey;
-
     /* set up vertical bands */
-    num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
-    if ( num_bands == 0 )
-      num_bands = 1;
-    if ( num_bands >= 39 )
-      num_bands = 39;
-
-    ras.band_shoot = 0;
+    if ( count > band_size )
+    {
+      /* two divisions rounded up */
+      num_bands = (int)( ( count + band_size - 1) / band_size );
+      band_size = ( count + num_bands - 1 ) / num_bands;
+    }
 
     min   = ras.min_ey;
     max_y = ras.max_ey;
 
-    for ( n = 0; n < num_bands; n++, min = max )
+    for ( ; min < max_y; min = max )
     {
-      max = min + ras.band_size;
-      if ( n == num_bands - 1 || max > max_y )
+      max = min + band_size;
+      if ( max > max_y )
         max = max_y;
 
-      bands[0].min = min;
-      bands[0].max = max;
-      band         = bands;
+      band    = bands;
+      band[1] = min;
+      band[0] = max;
 
-      while ( band >= bands )
+      do
       {
-        TPos  bottom, top, middle;
-        int   error;
+        TCoord  width = band[0] - band[1];
+        int     error;
 
+
+        /* memory management */
         {
-          PCell  cells_max;
-          int    yindex;
-          long   cell_start, cell_end, cell_mod;
+          size_t  ycount = (size_t)width;
+          size_t  cell_start;
 
 
-          ras.ycells = (PCell*)ras.buffer;
-          ras.ycount = band->max - band->min;
+          cell_start = ( ycount * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+                       sizeof ( TCell );
 
-          cell_start = sizeof ( PCell ) * ras.ycount;
-          cell_mod   = cell_start % sizeof ( TCell );
-          if ( cell_mod > 0 )
-            cell_start += sizeof ( TCell ) - cell_mod;
-
-          cell_end  = ras.buffer_size;
-          cell_end -= cell_end % sizeof ( TCell );
-
-          cells_max = (PCell)( (char*)ras.buffer + cell_end );
-          ras.cells = (PCell)( (char*)ras.buffer + cell_start );
-          if ( ras.cells >= cells_max )
+          if ( FT_MAX_GRAY_POOL - cell_start < 2 )
             goto ReduceBands;
 
-          ras.max_cells = cells_max - ras.cells;
-          if ( ras.max_cells < 2 )
-            goto ReduceBands;
+          ras.cells     = buffer + cell_start;
+          ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - cell_start );
 
-          for ( yindex = 0; yindex < ras.ycount; yindex++ )
-            ras.ycells[yindex] = NULL;
+          ras.ycells = (PCell*)buffer;
+          while ( ycount )
+            ras.ycells[--ycount] = NULL;
         }
 
         ras.num_cells = 0;
         ras.invalid   = 1;
-        ras.min_ey    = band->min;
-        ras.max_ey    = band->max;
-        ras.count_ey  = band->max - band->min;
+        ras.min_ey    = band[1];
+        ras.max_ey    = band[0];
 
         error = gray_convert_glyph_inner( RAS_VAR );
 
         if ( !error )
         {
-          gray_sweep( RAS_VAR_ &ras.target );
+          gray_sweep( RAS_VAR );
           band--;
           continue;
         }
@@ -1906,50 +1826,46 @@
 
       ReduceBands:
         /* render pool overflow; we will reduce the render band by half */
-        bottom = band->min;
-        top    = band->max;
-        middle = bottom + ( ( top - bottom ) >> 1 );
+        width >>= 1;
 
         /* This is too complex for a single scanline; there must */
         /* be some problems.                                     */
-        if ( middle == bottom )
+        if ( width == 0 )
         {
-#ifdef FT_DEBUG_LEVEL_TRACE
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
-#endif
           return 1;
         }
 
-        if ( bottom-top >= ras.band_size )
-          ras.band_shoot++;
-
-        band[1].min = bottom;
-        band[1].max = middle;
-        band[0].min = middle;
-        band[0].max = top;
         band++;
-      }
+        band[1]  = band[0];
+        band[0] += width;
+      } while ( band >= bands );
     }
 
-    if ( ras.band_shoot > 8 && ras.band_size > 16 )
-      ras.band_size = ras.band_size / 2;
-
     return 0;
   }
 
 
   static int
-  gray_raster_render( gray_PRaster             raster,
+  gray_raster_render( FT_Raster                raster,
                       const FT_Raster_Params*  params )
   {
-    const FT_Outline*  outline    = (const FT_Outline*)params->source;
-    const FT_Bitmap*   target_map = params->target;
-    gray_PWorker       worker;
+    const FT_Outline*  outline     = (const FT_Outline*)params->source;
+    const FT_Bitmap*   target_map  = params->target;
+    FT_BBox            cbox, clip;
+
+#ifndef FT_STATIC_RASTER
+    gray_TWorker  worker[1];
+#endif
 
 
-    if ( !raster || !raster->buffer || !raster->buffer_size )
+    if ( !raster )
       return FT_THROW( Invalid_Argument );
 
+    /* this version does not support monochrome rendering */
+    if ( !( params->flags & FT_RASTER_FLAG_AA ) )
+      return FT_THROW( Invalid_Mode );
+
     if ( !outline )
       return FT_THROW( Invalid_Outline );
 
@@ -1964,11 +1880,19 @@
            outline->contours[outline->n_contours - 1] + 1 )
       return FT_THROW( Invalid_Outline );
 
-    worker = raster->worker;
+    ras.outline = *outline;
 
-    /* if direct mode is not set, we must have a target bitmap */
-    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
+    if ( params->flags & FT_RASTER_FLAG_DIRECT )
     {
+      if ( !params->gray_spans )
+        return 0;
+
+      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
+      ras.render_span_data = params->user;
+    }
+    else
+    {
+      /* if direct mode is not set, we must have a target bitmap */
       if ( !target_map )
         return FT_THROW( Invalid_Argument );
 
@@ -1978,50 +1902,59 @@
 
       if ( !target_map->buffer )
         return FT_THROW( Invalid_Argument );
+
+      if ( target_map->pitch < 0 )
+        ras.target.origin = target_map->buffer;
+      else
+        ras.target.origin = target_map->buffer
+              + ( target_map->rows - 1 ) * (unsigned int)target_map->pitch;
+
+      ras.target.pitch = target_map->pitch;
+
+      ras.render_span      = (FT_Raster_Span_Func)NULL;
+      ras.render_span_data = NULL;
     }
 
-    /* this version does not support monochrome rendering */
-    if ( !( params->flags & FT_RASTER_FLAG_AA ) )
-      return FT_THROW( Invalid_Mode );
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    /* reject too large outline coordinates */
+    if ( cbox.xMin < -0x1000000L || cbox.xMax > 0x1000000L ||
+         cbox.yMin < -0x1000000L || cbox.yMax > 0x1000000L )
+      return FT_THROW( Invalid_Outline );
+
+    /* truncate the bounding box to integer pixels */
+    cbox.xMin = cbox.xMin >> 6;
+    cbox.yMin = cbox.yMin >> 6;
+    cbox.xMax = ( cbox.xMax + 63 ) >> 6;
+    cbox.yMax = ( cbox.yMax + 63 ) >> 6;
 
     /* compute clipping box */
     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
     {
       /* compute clip box from target pixmap */
-      ras.clip_box.xMin = 0;
-      ras.clip_box.yMin = 0;
-      ras.clip_box.xMax = target_map->width;
-      ras.clip_box.yMax = target_map->rows;
+      clip.xMin = 0;
+      clip.yMin = 0;
+      clip.xMax = (FT_Pos)target_map->width;
+      clip.yMax = (FT_Pos)target_map->rows;
     }
     else if ( params->flags & FT_RASTER_FLAG_CLIP )
-      ras.clip_box = params->clip_box;
+      clip = params->clip_box;
     else
     {
-      ras.clip_box.xMin = -32768L;
-      ras.clip_box.yMin = -32768L;
-      ras.clip_box.xMax =  32767L;
-      ras.clip_box.yMax =  32767L;
+      clip.xMin = -32768L;
+      clip.yMin = -32768L;
+      clip.xMax =  32767L;
+      clip.yMax =  32767L;
     }
 
-    gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
+    /* clip to target bitmap, exit if nothing to do */
+    ras.min_ex = FT_MAX( cbox.xMin, clip.xMin );
+    ras.min_ey = FT_MAX( cbox.yMin, clip.yMin );
+    ras.max_ex = FT_MIN( cbox.xMax, clip.xMax );
+    ras.max_ey = FT_MIN( cbox.yMax, clip.yMax );
 
-    ras.outline        = *outline;
-    ras.num_cells      = 0;
-    ras.invalid        = 1;
-    ras.band_size      = raster->band_size;
-    ras.num_gray_spans = 0;
-
-    if ( params->flags & FT_RASTER_FLAG_DIRECT )
-    {
-      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
-      ras.render_span_data = params->user;
-    }
-    else
-    {
-      ras.target           = *target_map;
-      ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
-      ras.render_span_data = &ras;
-    }
+    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
+      return 0;
 
     return gray_convert_glyph( RAS_VAR );
   }
@@ -2030,7 +1963,7 @@
   /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
   /****                         a static object.                   *****/
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
   static int
   gray_raster_new( void*       memory,
@@ -2055,7 +1988,7 @@
     FT_UNUSED( raster );
   }
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
   static int
   gray_raster_new( FT_Memory   memory,
@@ -2085,54 +2018,44 @@
     FT_FREE( raster );
   }
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
   static void
-  gray_raster_reset( FT_Raster  raster,
-                     char*      pool_base,
-                     long       pool_size )
+  gray_raster_reset( FT_Raster       raster,
+                     unsigned char*  pool_base,
+                     unsigned long   pool_size )
   {
-    gray_PRaster  rast = (gray_PRaster)raster;
-
-
-    if ( raster )
-    {
-      if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
-      {
-        gray_PWorker  worker = (gray_PWorker)pool_base;
-
-
-        rast->worker      = worker;
-        rast->buffer      = pool_base +
-                              ( ( sizeof ( gray_TWorker ) +
-                                  sizeof ( TCell ) - 1 )  &
-                                ~( sizeof ( TCell ) - 1 ) );
-        rast->buffer_size = (long)( ( pool_base + pool_size ) -
-                                    (char*)rast->buffer ) &
-                                      ~( sizeof ( TCell ) - 1 );
-        rast->band_size   = (int)( rast->buffer_size /
-                                     ( sizeof ( TCell ) * 8 ) );
-      }
-      else
-      {
-        rast->buffer      = NULL;
-        rast->buffer_size = 0;
-        rast->worker      = NULL;
-      }
-    }
+    FT_UNUSED( raster );
+    FT_UNUSED( pool_base );
+    FT_UNUSED( pool_size );
   }
 
 
-  FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
+  static int
+  gray_raster_set_mode( FT_Raster      raster,
+                        unsigned long  mode,
+                        void*          args )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( args );
+
+
+    return 0; /* nothing to do */
+  }
+
+
+  FT_DEFINE_RASTER_FUNCS(
+    ft_grays_raster,
+
     FT_GLYPH_FORMAT_OUTLINE,
 
     (FT_Raster_New_Func)     gray_raster_new,
     (FT_Raster_Reset_Func)   gray_raster_reset,
-    (FT_Raster_Set_Mode_Func)0,
+    (FT_Raster_Set_Mode_Func)gray_raster_set_mode,
     (FT_Raster_Render_Func)  gray_raster_render,
-    (FT_Raster_Done_Func)    gray_raster_done
-  )
+    (FT_Raster_Done_Func)    gray_raster_done )
 
 
 /* END */
diff --git a/src/smooth/ftgrays.h b/src/smooth/ftgrays.h
index f20f55f..21c2bad 100644
--- a/src/smooth/ftgrays.h
+++ b/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType smooth renderer declaration                                 */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,15 +16,15 @@
 /***************************************************************************/
 
 
-#ifndef __FTGRAYS_H__
-#define __FTGRAYS_H__
+#ifndef FTGRAYS_H_
+#define FTGRAYS_H_
 
 #ifdef __cplusplus
   extern "C" {
 #endif
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 #include "ftimage.h"
 #else
 #include <ft2build.h>
@@ -52,7 +52,7 @@
   }
 #endif
 
-#endif /* __FTGRAYS_H__ */
+#endif /* FTGRAYS_H_ */
 
 
 /* END */
diff --git a/src/smooth/ftsmerrs.h b/src/smooth/ftsmerrs.h
index 413d2f1..a759b91 100644
--- a/src/smooth/ftsmerrs.h
+++ b/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    smooth renderer error codes (specification only).                    */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,12 +23,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __FTSMERRS_H__
-#define __FTSMERRS_H__
+#ifndef FTSMERRS_H_
+#define FTSMERRS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  Smooth_Err_
@@ -36,7 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __FTSMERRS_H__ */
+#endif /* FTSMERRS_H_ */
 
 
 /* END */
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 89088cd..7927676 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (body).                             */
 /*                                                                         */
-/*  Copyright 2000-2006, 2009-2013 by                                      */
+/*  Copyright 2000-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -103,25 +103,24 @@
                             FT_Render_Mode    required_mode )
   {
     FT_Error     error;
-    FT_Outline*  outline = NULL;
+    FT_Outline*  outline = &slot->outline;
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+    FT_Memory    memory  = render->root.memory;
     FT_BBox      cbox;
+    FT_Pos       x_shift = 0;
+    FT_Pos       y_shift = 0;
+    FT_Pos       x_left, y_top;
     FT_Pos       width, height, pitch;
 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     FT_Pos       height_org, width_org;
 #endif
-    FT_Bitmap*   bitmap  = &slot->bitmap;
-    FT_Memory    memory  = render->root.memory;
     FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
     FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
-    FT_Pos       x_shift = 0;
-    FT_Pos       y_shift = 0;
-    FT_Pos       x_left, y_top;
 
     FT_Raster_Params  params;
 
-    FT_Bool  have_translated_origin = FALSE;
-    FT_Bool  have_outline_shifted   = FALSE;
-    FT_Bool  have_buffer            = FALSE;
+    FT_Bool  have_outline_shifted = FALSE;
+    FT_Bool  have_buffer          = FALSE;
 
 
     /* check glyph image format */
@@ -138,73 +137,45 @@
       goto Exit;
     }
 
-    outline = &slot->outline;
-
-    /* translate the outline to the new origin if needed */
     if ( origin )
     {
-      FT_Outline_Translate( outline, origin->x, origin->y );
-      have_translated_origin = TRUE;
+      x_shift = origin->x;
+      y_shift = origin->y;
     }
 
     /* compute the control box, and grid fit it */
+    /* taking into account the origin shift     */
     FT_Outline_Get_CBox( outline, &cbox );
 
-    cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
-    cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
-    cbox.xMax = FT_PIX_CEIL( cbox.xMax );
-    cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+    cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
+    cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
+    cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
+    cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
 
-    if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
-    {
-      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
-                 " xMin = %d, xMax = %d\n",
-                 cbox.xMin >> 6, cbox.xMax >> 6 ));
-      error = FT_THROW( Raster_Overflow );
-      goto Exit;
-    }
-    else
-      width = ( cbox.xMax - cbox.xMin ) >> 6;
+    x_shift -= cbox.xMin;
+    y_shift -= cbox.yMin;
 
-    if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
-    {
-      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
-                 " yMin = %d, yMax = %d\n",
-                 cbox.yMin >> 6, cbox.yMax >> 6 ));
-      error = FT_THROW( Raster_Overflow );
-      goto Exit;
-    }
-    else
-      height = ( cbox.yMax - cbox.yMin ) >> 6;
+    x_left  = cbox.xMin >> 6;
+    y_top   = cbox.yMax >> 6;
+
+    width  = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
+    height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
 
 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     width_org  = width;
     height_org = height;
 #endif
 
-    /* release old bitmap buffer */
-    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
-    {
-      FT_FREE( bitmap->buffer );
-      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
-    }
-
-    /* allocate new one */
     pitch = width;
     if ( hmul )
     {
-      width = width * 3;
-      pitch = FT_PAD_CEIL( width, 4 );
+      width *= 3;
+      pitch  = FT_PAD_CEIL( width, 4 );
     }
 
     if ( vmul )
       height *= 3;
 
-    x_shift = (FT_Int) cbox.xMin;
-    y_shift = (FT_Int) cbox.yMin;
-    x_left  = (FT_Int)( cbox.xMin >> 6 );
-    y_top   = (FT_Int)( cbox.yMax >> 6 );
-
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
 
     if ( slot->library->lcd_filter_func )
@@ -214,23 +185,32 @@
 
       if ( hmul )
       {
-        x_shift -= 64 * ( extra >> 1 );
+        x_shift += 64 * ( extra >> 1 );
+        x_left  -= extra >> 1;
         width   += 3 * extra;
         pitch    = FT_PAD_CEIL( width, 4 );
-        x_left  -= extra >> 1;
       }
 
       if ( vmul )
       {
-        y_shift -= 64 * ( extra >> 1 );
-        height  += 3 * extra;
+        y_shift += 64 * ( extra >> 1 );
         y_top   += extra >> 1;
+        height  += 3 * extra;
       }
     }
 
 #endif
 
-#if FT_UINT_MAX > 0xFFFFU
+    /*
+     * XXX: on 16bit system, we return an error for huge bitmap
+     * to prevent an overflow.
+     */
+    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
+         x_left < FT_INT_MIN || y_top < FT_INT_MIN )
+    {
+      error = FT_THROW( Invalid_Pixel_Size );
+      goto Exit;
+    }
 
     /* Required check is (pitch * height < FT_ULONG_MAX),        */
     /* but we care realistic cases only.  Always pitch <= width. */
@@ -242,25 +222,38 @@
       goto Exit;
     }
 
-#endif
+    /* release old bitmap buffer */
+    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+    {
+      FT_FREE( bitmap->buffer );
+      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
 
-    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
-    bitmap->num_grays  = 256;
-    bitmap->width      = width;
-    bitmap->rows       = height;
-    bitmap->pitch      = pitch;
-
-    /* translate outline to render it into the bitmap */
-    FT_Outline_Translate( outline, -x_shift, -y_shift );
-    have_outline_shifted = TRUE;
-
-    if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+    /* allocate new one */
+    if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
       goto Exit;
     else
       have_buffer = TRUE;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
+    slot->format      = FT_GLYPH_FORMAT_BITMAP;
+    slot->bitmap_left = (FT_Int)x_left;
+    slot->bitmap_top  = (FT_Int)y_top;
+
+    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+    bitmap->num_grays  = 256;
+    bitmap->width      = (unsigned int)width;
+    bitmap->rows       = (unsigned int)height;
+    bitmap->pitch      = pitch;
+
+    /* translate outline to render it into the bitmap */
+    if ( x_shift || y_shift )
+    {
+      FT_Outline_Translate( outline, x_shift, y_shift );
+      have_outline_shifted = TRUE;
+    }
+
     /* set up parameters */
     params.target = bitmap;
     params.source = outline;
@@ -366,20 +359,6 @@
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-    /*
-     * XXX: on 16bit system, we return an error for huge bitmap
-     * to prevent an overflow.
-     */
-    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
-    {
-      error = FT_THROW( Invalid_Pixel_Size );
-      goto Exit;
-    }
-
-    slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = (FT_Int)x_left;
-    slot->bitmap_top  = (FT_Int)y_top;
-
     /* everything is fine; don't deallocate buffer */
     have_buffer = FALSE;
 
@@ -387,9 +366,7 @@
 
   Exit:
     if ( have_outline_shifted )
-      FT_Outline_Translate( outline, x_shift, y_shift );
-    if ( have_translated_origin )
-      FT_Outline_Translate( outline, -origin->x, -origin->y );
+      FT_Outline_Translate( outline, -x_shift, -y_shift );
     if ( have_buffer )
     {
       FT_FREE( bitmap->buffer );
diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h
index 3708790..c7c28c2 100644
--- a/src/smooth/ftsmooth.h
+++ b/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTSMOOTH_H__
-#define __FTSMOOTH_H__
+#ifndef FTSMOOTH_H_
+#define FTSMOOTH_H_
 
 
 #include <ft2build.h>
@@ -43,7 +43,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTSMOOTH_H__ */
+#endif /* FTSMOOTH_H_ */
 
 
 /* END */
diff --git a/src/smooth/ftspic.c b/src/smooth/ftspic.c
index 67a2b83..6c2b232 100644
--- a/src/smooth/ftspic.c
+++ b/src/smooth/ftspic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for smooth module.   */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/smooth/ftspic.h b/src/smooth/ftspic.h
index 334b51c..fe76152 100644
--- a/src/smooth/ftspic.h
+++ b/src/smooth/ftspic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for smooth module.   */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,14 +16,15 @@
 /***************************************************************************/
 
 
-#ifndef __FTSPIC_H__
-#define __FTSPIC_H__
+#ifndef FTSPIC_H_
+#define FTSPIC_H_
+
+
+#include FT_INTERNAL_PIC_H
 
 
 FT_BEGIN_HEADER
 
-#include FT_INTERNAL_PIC_H
-
 #ifndef FT_CONFIG_OPTION_PIC
 
 #define FT_GRAYS_RASTER_GET  ft_grays_raster
@@ -68,7 +69,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTSPIC_H__ */
+#endif /* FTSPIC_H_ */
 
 
 /* END */
diff --git a/src/smooth/smooth.c b/src/smooth/smooth.c
index a8ac51f..97ca3e5 100644
--- a/src/smooth/smooth.c
+++ b/src/smooth/smooth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType anti-aliasing rasterer module component (body only).        */
 /*                                                                         */
-/*  Copyright 1996-2001 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/truetype/truetype.c b/src/truetype/truetype.c
index 576912b..23e2ea0 100644
--- a/src/truetype/truetype.c
+++ b/src/truetype/truetype.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType TrueType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2006, 2012 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index 36d23a2..b96a227 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2013 by                                                 */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,7 +20,7 @@
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_SFNT_H
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include FT_MULTIPLE_MASTERS_H
@@ -61,23 +61,50 @@
   static FT_Error
   tt_property_set( FT_Module    module,         /* TT_Driver */
                    const char*  property_name,
-                   const void*  value )
+                   const void*  value,
+                   FT_Bool      value_is_string )
   {
     FT_Error   error  = FT_Err_Ok;
     TT_Driver  driver = (TT_Driver)module;
 
+#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+    FT_UNUSED( value_is_string );
+#endif
+
 
     if ( !ft_strcmp( property_name, "interpreter-version" ) )
     {
-      FT_UInt*  interpreter_version = (FT_UInt*)value;
+      FT_UInt  interpreter_version;
 
 
-#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
-        error = FT_ERR( Unimplemented_Feature );
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
+
+
+        interpreter_version = (FT_UInt)ft_strtol( s, NULL, 10 );
+      }
       else
 #endif
-        driver->interpreter_version = *interpreter_version;
+      {
+        FT_UInt*  iv = (FT_UInt*)value;
+
+
+        interpreter_version = *iv;
+      }
+
+      if ( interpreter_version == TT_INTERPRETER_VERSION_35
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+           || interpreter_version == TT_INTERPRETER_VERSION_38
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+           || interpreter_version == TT_INTERPRETER_VERSION_40
+#endif
+         )
+        driver->interpreter_version = interpreter_version;
+      else
+        error = FT_ERR( Unimplemented_Feature );
 
       return error;
     }
@@ -117,8 +144,8 @@
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     tt_service_properties,
-    (FT_Properties_SetFunc)tt_property_set,
-    (FT_Properties_GetFunc)tt_property_get )
+    (FT_Properties_SetFunc)tt_property_set,     /* set_property */
+    (FT_Properties_GetFunc)tt_property_get )    /* get_property */
 
 
   /*************************************************************************/
@@ -134,11 +161,6 @@
   /*************************************************************************/
 
 
-#undef  PAIR_TAG
-#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
-                                     (FT_ULong)right        )
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -191,9 +213,6 @@
   }
 
 
-#undef PAIR_TAG
-
-
   static FT_Error
   tt_get_advances( FT_Face    ttface,
                    FT_UInt    start,
@@ -202,7 +221,7 @@
                    FT_Fixed  *advances )
   {
     FT_UInt  nn;
-    TT_Face  face  = (TT_Face) ttface;
+    TT_Face  face = (TT_Face) ttface;
 
 
     /* XXX: TODO: check for sbits */
@@ -236,6 +255,7 @@
     return FT_Err_Ok;
   }
 
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -267,11 +287,11 @@
       /* use the scaled metrics, even when tt_size_reset fails */
       FT_Select_Metrics( size->face, strike_index );
 
-      tt_size_reset( ttsize );
+      tt_size_reset( ttsize ); /* ignore return value */
     }
     else
     {
-      SFNT_Service      sfnt    = (SFNT_Service) ttface->sfnt;
+      SFNT_Service      sfnt    = (SFNT_Service)ttface->sfnt;
       FT_Size_Metrics*  metrics = &size->metrics;
 
 
@@ -299,7 +319,7 @@
     if ( FT_HAS_FIXED_SIZES( size->face ) )
     {
       TT_Face       ttface = (TT_Face)size->face;
-      SFNT_Service  sfnt   = (SFNT_Service) ttface->sfnt;
+      SFNT_Service  sfnt   = (SFNT_Service)ttface->sfnt;
       FT_ULong      strike_index;
 
 
@@ -319,6 +339,25 @@
     {
       error = tt_size_reset( ttsize );
       ttsize->root.metrics = ttsize->metrics;
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+      /* for the `MPS' bytecode instruction we need the point size */
+      {
+        FT_UInt  resolution = ttsize->metrics.x_ppem > ttsize->metrics.y_ppem
+                                ? req->horiResolution
+                                : req->vertResolution;
+
+
+        /* if we don't have a resolution value, assume 72dpi */
+        if ( req->type == FT_SIZE_REQUEST_TYPE_SCALES ||
+             !resolution                              )
+          resolution = 72;
+
+        ttsize->point_size = FT_MulDiv( ttsize->ttmetrics.ppem,
+                                        64 * 72,
+                                        resolution );
+      }
+#endif
     }
 
     return error;
@@ -370,7 +409,7 @@
       return FT_THROW( Invalid_Size_Handle );
 
     if ( !face )
-      return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Face_Handle );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     if ( glyph_index >= (FT_UInt)face->num_glyphs &&
@@ -425,22 +464,19 @@
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   FT_DEFINE_SERVICE_MULTIMASTERSREC(
     tt_service_gx_multi_masters,
-    (FT_Get_MM_Func)        NULL,
-    (FT_Set_MM_Design_Func) NULL,
-    (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,
-    (FT_Get_MM_Var_Func)    TT_Get_MM_Var,
-    (FT_Set_Var_Design_Func)TT_Set_Var_Design )
+    (FT_Get_MM_Func)        NULL,                   /* get_mm         */
+    (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
+    (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,        /* set_mm_blend   */
+    (FT_Get_MM_Var_Func)    TT_Get_MM_Var,          /* get_mm_var     */
+    (FT_Set_Var_Design_Func)TT_Set_Var_Design )     /* set_var_design */
 #endif
 
+
   static const FT_Service_TrueTypeEngineRec  tt_service_truetype_engine =
   {
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_TRUETYPE_ENGINE_TYPE_UNPATENTED
-#else
     FT_TRUETYPE_ENGINE_TYPE_PATENTED
-#endif
 
 #else /* !TT_USE_BYTECODE_INTERPRETER */
 
@@ -449,14 +485,16 @@
 #endif /* TT_USE_BYTECODE_INTERPRETER */
   };
 
+
   FT_DEFINE_SERVICE_TTGLYFREC(
     tt_service_truetype_glyf,
-    (TT_Glyf_GetLocationFunc)tt_face_get_location )
+    (TT_Glyf_GetLocationFunc)tt_face_get_location )    /* get_location */
+
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   FT_DEFINE_SERVICEDESCREC5(
     tt_services,
-    FT_SERVICE_ID_XF86_NAME,       FT_XF86_FORMAT_TRUETYPE,
+    FT_SERVICE_ID_FONT_FORMAT,     FT_FONT_FORMAT_TRUETYPE,
     FT_SERVICE_ID_MULTI_MASTERS,   &TT_SERVICE_GX_MULTI_MASTERS_GET,
     FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
     FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
@@ -464,7 +502,7 @@
 #else
   FT_DEFINE_SERVICEDESCREC4(
     tt_services,
-    FT_SERVICE_ID_XF86_NAME,       FT_XF86_FORMAT_TRUETYPE,
+    FT_SERVICE_ID_FONT_FORMAT,     FT_FONT_FORMAT_TRUETYPE,
     FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
     FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
     FT_SERVICE_ID_PROPERTIES,      &TT_SERVICE_PROPERTIES_GET )
@@ -481,7 +519,7 @@
     SFNT_Service         sfnt;
 
 
-    /* TT_SERVICES_GET derefers `library' in PIC mode */
+    /* TT_SERVICES_GET dereferences `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     if ( !driver )
       return NULL;
@@ -542,31 +580,31 @@
       0x10000L,        /* driver version == 1.0                 */
       0x20000L,        /* driver requires FreeType 2.0 or above */
 
-      (void*)0,        /* driver specific interface */
+      0,    /* module-specific interface */
 
-      tt_driver_init,
-      tt_driver_done,
-      tt_get_interface,
+      tt_driver_init,           /* FT_Module_Constructor  module_init   */
+      tt_driver_done,           /* FT_Module_Destructor   module_done   */
+      tt_get_interface,         /* FT_Module_Requester    get_interface */
 
     sizeof ( TT_FaceRec ),
     sizeof ( TT_SizeRec ),
     sizeof ( FT_GlyphSlotRec ),
 
-    tt_face_init,
-    tt_face_done,
-    tt_size_init,
-    tt_size_done,
-    tt_slot_init,
-    0,                       /* FT_Slot_DoneFunc */
+    tt_face_init,               /* FT_Face_InitFunc  init_face */
+    tt_face_done,               /* FT_Face_DoneFunc  done_face */
+    tt_size_init,               /* FT_Size_InitFunc  init_size */
+    tt_size_done,               /* FT_Size_DoneFunc  done_size */
+    tt_slot_init,               /* FT_Slot_InitFunc  init_slot */
+    0,                          /* FT_Slot_DoneFunc  done_slot */
 
-    tt_glyph_load,
+    tt_glyph_load,              /* FT_Slot_LoadFunc  load_glyph */
 
-    tt_get_kerning,
-    0,                       /* FT_Face_AttachFunc */
-    tt_get_advances,
+    tt_get_kerning,             /* FT_Face_GetKerningFunc   get_kerning  */
+    0,                          /* FT_Face_AttachFunc       attach_file  */
+    tt_get_advances,            /* FT_Face_GetAdvancesFunc  get_advances */
 
-    tt_size_request,
-    TT_SIZE_SELECT
+    tt_size_request,            /* FT_Size_RequestFunc  request_size */
+    TT_SIZE_SELECT              /* FT_Size_SelectFunc   select_size  */
   )
 
 
diff --git a/src/truetype/ttdriver.h b/src/truetype/ttdriver.h
index aae00f2..74392bb 100644
--- a/src/truetype/ttdriver.h
+++ b/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level TrueType driver interface (specification).                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTDRIVER_H__
-#define __TTDRIVER_H__
+#ifndef TTDRIVER_H_
+#define TTDRIVER_H_
 
 
 #include <ft2build.h>
@@ -32,7 +32,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTDRIVER_H__ */
+#endif /* TTDRIVER_H_ */
 
 
 /* END */
diff --git a/src/truetype/tterrors.h b/src/truetype/tterrors.h
index 78d138f..895989f 100644
--- a/src/truetype/tterrors.h
+++ b/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType error codes (specification only).                           */
 /*                                                                         */
-/*  Copyright 2001, 2012 by                                                */
+/*  Copyright 2001-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,12 +23,12 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifndef __TTERRORS_H__
-#define __TTERRORS_H__
+#ifndef TTERRORS_H_
+#define TTERRORS_H_
 
 #include FT_MODULE_ERRORS_H
 
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
 
 #undef  FT_ERR_PREFIX
 #define FT_ERR_PREFIX  TT_Err_
@@ -36,6 +36,7 @@
 
 #include FT_ERRORS_H
 
-#endif /* __TTERRORS_H__ */
+#endif /* TTERRORS_H_ */
+
 
 /* END */
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index ff2b339..2d0b29f 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2014                                                    */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,6 +24,7 @@
 #include FT_TRUETYPE_TAGS_H
 #include FT_OUTLINE_H
 #include FT_TRUETYPE_DRIVER_H
+#include FT_LIST_H
 
 #include "ttgload.h"
 #include "ttpload.h"
@@ -100,13 +101,15 @@
     else if ( face->os2.version != 0xFFFFU )
     {
       *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
-      *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
+      *ah  = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
+                                face->os2.sTypoDescender );
     }
 
     else
     {
       *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
-      *ah  = face->horizontal.Ascender - face->horizontal.Descender;
+      *ah  = (FT_UShort)FT_ABS( face->horizontal.Ascender -
+                                face->horizontal.Descender );
     }
 
     FT_TRACE5(( "  advance height (font units): %d\n", *ah ));
@@ -118,8 +121,8 @@
   tt_get_metrics( TT_Loader  loader,
                   FT_UInt    glyph_index )
   {
-    TT_Face    face   = (TT_Face)loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Face    face   = loader->face;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
@@ -150,17 +153,19 @@
     loader->top_bearing  = top_bearing;
     loader->vadvance     = advance_height;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+         loader->exec                                             )
     {
-      if ( loader->exec )
-        loader->exec->sph_tweak_flags = 0;
+      loader->exec->sph_tweak_flags = 0;
 
-      /* this may not be the right place for this, but it works */
-      if ( loader->exec && loader->exec->ignore_x_mode )
-        sph_set_tweaks( loader, glyph_index );
+      /* This may not be the right place for this, but it works...  */
+      /* Note that we have to unconditionally load the tweaks since */
+      /* it is possible that glyphs individually switch ClearType's */
+      /* backwards compatibility mode on and off.                   */
+      sph_set_tweaks( loader, glyph_index );
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( !loader->linear_def )
     {
@@ -178,7 +183,7 @@
   tt_get_metrics_incr_overrides( TT_Loader  loader,
                                  FT_UInt    glyph_index )
   {
-    TT_Face  face = (TT_Face)loader->face;
+    TT_Face  face = loader->face;
 
     FT_Short   left_bearing = 0, top_bearing = 0;
     FT_UShort  advance_width = 0, advance_height = 0;
@@ -246,29 +251,6 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Translates an array of coordinates.                                   */
-  /*                                                                       */
-  static void
-  translate_array( FT_UInt     n,
-                   FT_Vector*  coords,
-                   FT_Pos      delta_x,
-                   FT_Pos      delta_y )
-  {
-    FT_UInt  k;
-
-
-    if ( delta_x )
-      for ( k = 0; k < n; k++ )
-        coords[k].x += delta_x;
-
-    if ( delta_y )
-      for ( k = 0; k < n; k++ )
-        coords[k].y += delta_y;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
   /* The following functions are used by default with TrueType fonts.      */
   /* However, they can be replaced by alternatives if we need to support   */
   /* TrueType-compressed formats (like MicroType) in the future.           */
@@ -407,7 +389,7 @@
 
     /* reading the bytecode instructions */
     load->glyph->control_len  = 0;
-    load->glyph->control_data = 0;
+    load->glyph->control_data = NULL;
 
     if ( p + 2 > limit )
       goto Invalid_Outline;
@@ -445,7 +427,8 @@
       load->glyph->control_len  = n_ins;
       load->glyph->control_data = load->exec->glyphIns;
 
-      FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
+      if ( n_ins )
+        FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
     }
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -555,8 +538,8 @@
       *flag  = (FT_Byte)( f & FT_CURVE_TAG_ON );
     }
 
-    outline->n_points   = (FT_UShort)n_points;
-    outline->n_contours = (FT_Short) n_contours;
+    outline->n_points   = (FT_Short)n_points;
+    outline->n_contours = (FT_Short)n_contours;
 
     load->cursor = p;
 
@@ -619,15 +602,31 @@
         goto Invalid_Composite;
 
       /* read arguments */
-      if ( subglyph->flags & ARGS_ARE_WORDS )
+      if ( subglyph->flags & ARGS_ARE_XY_VALUES )
       {
-        subglyph->arg1 = FT_NEXT_SHORT( p );
-        subglyph->arg2 = FT_NEXT_SHORT( p );
+        if ( subglyph->flags & ARGS_ARE_WORDS )
+        {
+          subglyph->arg1 = FT_NEXT_SHORT( p );
+          subglyph->arg2 = FT_NEXT_SHORT( p );
+        }
+        else
+        {
+          subglyph->arg1 = FT_NEXT_CHAR( p );
+          subglyph->arg2 = FT_NEXT_CHAR( p );
+        }
       }
       else
       {
-        subglyph->arg1 = FT_NEXT_CHAR( p );
-        subglyph->arg2 = FT_NEXT_CHAR( p );
+        if ( subglyph->flags & ARGS_ARE_WORDS )
+        {
+          subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
+          subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
+        }
+        else
+        {
+          subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
+          subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
+        }
       }
 
       /* read transform */
@@ -636,20 +635,20 @@
 
       if ( subglyph->flags & WE_HAVE_A_SCALE )
       {
-        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
         yy = xx;
       }
       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
       {
-        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
-        yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+        yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
       }
       else if ( subglyph->flags & WE_HAVE_A_2X2 )
       {
-        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
-        yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
-        xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
-        yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+        yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+        xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+        yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
       }
 
       subglyph->transform.xx = xx;
@@ -662,6 +661,7 @@
     } while ( subglyph->flags & MORE_COMPONENTS );
 
     gloader->current.num_subglyphs = num_subglyphs;
+    FT_TRACE5(( "  %d components\n", num_subglyphs ));
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
@@ -707,9 +707,10 @@
                    FT_UInt       start_point,
                    FT_UInt       start_contour )
   {
-    zone->n_points    = (FT_UShort)( load->outline.n_points - start_point );
-    zone->n_contours  = (FT_Short) ( load->outline.n_contours -
-                                       start_contour );
+    zone->n_points    = (FT_UShort)load->outline.n_points -
+                          (FT_UShort)start_point;
+    zone->n_contours  = load->outline.n_contours -
+                          (FT_Short)start_contour;
     zone->org         = load->extra_points + start_point;
     zone->cur         = load->outline.points + start_point;
     zone->orus        = load->extra_points2 + start_point;
@@ -732,15 +733,16 @@
   TT_Hint_Glyph( TT_Loader  loader,
                  FT_Bool    is_composite )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    TT_Face    face   = (TT_Face)loader->face;
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    TT_Face    face   = loader->face;
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
     TT_GlyphZone  zone = &loader->zone;
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
-    FT_UInt       n_ins;
+    FT_Long       n_ins;
 #else
     FT_UNUSED( is_composite );
 #endif
@@ -753,14 +755,14 @@
       FT_TRACE1(( " (0x%lx byte) is truncated\n",
                  loader->glyph->control_len ));
     }
-    n_ins = (FT_UInt)( loader->glyph->control_len );
+    n_ins = loader->glyph->control_len;
 
     /* save original point position in org */
     if ( n_ins > 0 )
       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
 
     /* Reset graphics state. */
-    loader->exec->GS = ((TT_Size)loader->size)->GS;
+    loader->exec->GS = loader->size->GS;
 
     /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
     /*      completely refer to the (already) hinted subglyphs.     */
@@ -773,10 +775,8 @@
     }
     else
     {
-      loader->exec->metrics.x_scale =
-        ((TT_Size)loader->size)->metrics.x_scale;
-      loader->exec->metrics.y_scale =
-        ((TT_Size)loader->size)->metrics.y_scale;
+      loader->exec->metrics.x_scale = loader->size->metrics.x_scale;
+      loader->exec->metrics.y_scale = loader->size->metrics.y_scale;
     }
 #endif
 
@@ -794,25 +794,19 @@
 
     if ( n_ins > 0 )
     {
-      FT_Bool   debug;
       FT_Error  error;
 
       FT_GlyphLoader  gloader         = loader->gloader;
       FT_Outline      current_outline = gloader->current.outline;
 
 
-      error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
-                                loader->exec->glyphIns, n_ins );
-      if ( error )
-        return error;
+      TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
+                        loader->exec->glyphIns, n_ins );
 
       loader->exec->is_composite = is_composite;
       loader->exec->pts          = *zone;
 
-      debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
-                       ((TT_Size)loader->size)->debug             );
-
-      error = TT_Run_Context( loader->exec, debug );
+      error = TT_Run_Context( loader->exec );
       if ( error && loader->exec->pedantic_hinting )
         return error;
 
@@ -823,13 +817,23 @@
 
 #endif
 
-    /* save glyph phantom points */
-    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_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* Save possibly modified glyph phantom points unless in v40 backwards */
+    /* compatibility mode, where no movement on the x axis means no reason */
+    /* to change bearings or advance widths.                               */
+    if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+            !loader->exec->backwards_compatibility ) )
+    {
+#endif
+      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_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    }
+#endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
     {
       if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
@@ -838,7 +842,7 @@
       else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
         FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     return FT_Err_Ok;
   }
@@ -882,28 +886,15 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    if ( ((TT_Face)loader->face)->doblend )
+    if ( loader->face->doblend )
     {
       /* Deltas apply to the unscaled data. */
-      FT_Vector*  deltas;
-      FT_Memory   memory = loader->face->memory;
-      FT_Int      i;
-
-
-      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
-                                        loader->glyph_index,
-                                        &deltas,
-                                        n_points );
+      error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+                                          loader->glyph_index,
+                                          outline,
+                                          (FT_UInt)n_points );
       if ( error )
         return error;
-
-      for ( i = 0; i < n_points; ++i )
-      {
-        outline->points[i].x += deltas[i].x;
-        outline->points[i].y += deltas[i].y;
-      }
-
-      FT_FREE( deltas );
     }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -917,14 +908,14 @@
     }
 
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      TT_Face    face   = (TT_Face)loader->face;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      TT_Face    face   = loader->face;
       TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 
       FT_String*  family         = face->root.family_name;
-      FT_Int      ppem           = loader->size->metrics.x_ppem;
+      FT_UInt     ppem           = loader->size->metrics.x_ppem;
       FT_String*  style          = face->root.style_name;
-      FT_Int      x_scale_factor = 1000;
+      FT_UInt     x_scale_factor = 1000;
 #endif
 
       FT_Vector*  vec   = outline->points;
@@ -936,7 +927,7 @@
       FT_Bool  do_scale = FALSE;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
@@ -951,9 +942,9 @@
         if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
              x_scale_factor != 1000                         )
         {
-          x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale,
-                               x_scale_factor, 1000 );
-          y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+          x_scale = FT_MulDiv( loader->size->metrics.x_scale,
+                               (FT_Long)x_scale_factor, 1000 );
+          y_scale = loader->size->metrics.y_scale;
 
           /* compensate for any scaling by de/emboldening; */
           /* the amount was determined via experimentation */
@@ -967,14 +958,14 @@
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         /* scale the glyph */
         if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
         {
-          x_scale = ((TT_Size)loader->size)->metrics.x_scale;
-          y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+          x_scale = loader->size->metrics.x_scale;
+          y_scale = loader->size->metrics.y_scale;
 
           do_scale = TRUE;
         }
@@ -1021,32 +1012,31 @@
                                   FT_UInt      start_point,
                                   FT_UInt      num_base_points )
   {
-    FT_GlyphLoader  gloader    = loader->gloader;
-    FT_Vector*      base_vec   = gloader->base.outline.points;
-    FT_UInt         num_points = gloader->base.outline.n_points;
+    FT_GlyphLoader  gloader = loader->gloader;
+    FT_Outline      current;
     FT_Bool         have_scale;
     FT_Pos          x, y;
 
 
+    current.points   = gloader->base.outline.points +
+                         num_base_points;
+    current.n_points = gloader->base.outline.n_points -
+                         (short)num_base_points;
+
     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
                                               WE_HAVE_AN_XY_SCALE |
                                               WE_HAVE_A_2X2       ) );
 
     /* perform the transform required for this subglyph */
     if ( have_scale )
-    {
-      FT_UInt  i;
-
-
-      for ( i = num_base_points; i < num_points; i++ )
-        FT_Vector_Transform( base_vec + i, &subglyph->transform );
-    }
+      FT_Outline_Transform( &current, &subglyph->transform );
 
     /* get offset */
     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
     {
-      FT_UInt     k = subglyph->arg1;
-      FT_UInt     l = subglyph->arg2;
+      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
+      FT_UInt     k = (FT_UInt)subglyph->arg1;
+      FT_UInt     l = (FT_UInt)subglyph->arg2;
       FT_Vector*  p1;
       FT_Vector*  p2;
 
@@ -1099,7 +1089,7 @@
                                             : -subglyph->transform.yx;
         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
                                             : -subglyph->transform.xy;
-        int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
+        int  d = subglyph->transform.yy > 0 ?  subglyph->transform.yy
                                             : -subglyph->transform.yy;
         int  m = a > b ? a : b;
         int  n = c > d ? c : d;
@@ -1133,8 +1123,8 @@
 
       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
       {
-        FT_Fixed  x_scale = ((TT_Size)loader->size)->metrics.x_scale;
-        FT_Fixed  y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+        FT_Fixed  x_scale = loader->size->metrics.x_scale;
+        FT_Fixed  y_scale = loader->size->metrics.y_scale;
 
 
         x = FT_MulFix( x, x_scale );
@@ -1149,9 +1139,7 @@
     }
 
     if ( x || y )
-      translate_array( num_points - num_base_points,
-                       base_vec + num_base_points,
-                       x, y );
+      FT_Outline_Translate( &current, x, y );
 
     return FT_Err_Ok;
   }
@@ -1213,7 +1201,7 @@
       FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
 
       /* check it */
-      max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
+      max_ins = loader->face->max_profile.maxSizeOfInstructions;
       if ( n_ins > max_ins )
       {
         /* don't trust `maxSizeOfInstructions'; */
@@ -1347,46 +1335,71 @@
    * (3) for everything else.
    *
    */
+  static void
+  tt_loader_set_pp( TT_Loader  loader )
+  {
+    FT_Bool  subpixel_hinting = 0;
+    FT_Bool  grayscale        = 0;
+    FT_Bool  use_aw_2         = 0;
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
+#endif
 
-#define TT_LOADER_SET_PP( loader )                                          \
-          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 )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    {
+      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
+                                      : 0;
+      grayscale        = loader->exec ? loader->exec->grayscale
+                                      : 0;
+    }
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+    {
+      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
+                                      : 0;
+      grayscale        = loader->exec ? loader->exec->grayscale_cleartype
+                                      : 0;
+    }
+#endif
 
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    use_aw_2 = (FT_Bool)( subpixel_hinting && grayscale );
 
-#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)->bbox.yMax + (loader)->top_bearing;  \
-            (loader)->pp4.x = 0;                                            \
-            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
-          } while ( 0 )
+    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;
 
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    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;
+  }
+
+
+  /* a utility function to retrieve i-th node from given FT_List */
+  static FT_ListNode
+  ft_list_get_node_at( FT_List  list,
+                       FT_UInt  index )
+  {
+    FT_ListNode  cur;
+
+
+    if ( !list )
+      return NULL;
+
+    for ( cur = list->head; cur; cur = cur->next )
+    {
+      if ( !index )
+        return cur;
+
+      index--;
+    }
+
+    return NULL;
+  }
 
 
   /*************************************************************************/
@@ -1407,14 +1420,10 @@
     FT_Error        error        = FT_Err_Ok;
     FT_Fixed        x_scale, y_scale;
     FT_ULong        offset;
-    TT_Face         face         = (TT_Face)loader->face;
+    TT_Face         face         = loader->face;
     FT_GlyphLoader  gloader      = loader->gloader;
     FT_Bool         opened_frame = 0;
 
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-    FT_Vector*      deltas       = NULL;
-#endif
-
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     FT_StreamRec    inc_stream;
     FT_Data         glyph_data;
@@ -1422,28 +1431,34 @@
 #endif
 
 
-    /* some fonts have an incorrect value of `maxComponentDepth', */
-    /* thus we allow depth 1 to catch the majority of them        */
-    if ( recurse_count > 1                                   &&
-         recurse_count > face->max_profile.maxComponentDepth )
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( recurse_count )
+      FT_TRACE5(( "  nesting level: %d\n", recurse_count ));
+#endif
+
+    /* some fonts have an incorrect value of `maxComponentDepth' */
+    if ( recurse_count > face->max_profile.maxComponentDepth )
     {
-      error = FT_THROW( Invalid_Composite );
-      goto Exit;
+      FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
+                  recurse_count ));
+      face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
     }
 
+#ifndef FT_CONFIG_OPTION_INCREMENTAL
     /* check glyph index */
     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
     {
       error = FT_THROW( Invalid_Glyph_Index );
       goto Exit;
     }
+#endif
 
     loader->glyph_index = glyph_index;
 
     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
     {
-      x_scale = ((TT_Size)loader->size)->metrics.x_scale;
-      y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+      x_scale = loader->size->metrics.x_scale;
+      y_scale = loader->size->metrics.y_scale;
     }
     else
     {
@@ -1474,7 +1489,8 @@
 
       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
       FT_Stream_OpenMemory( &inc_stream,
-                            glyph_data.pointer, glyph_data.length );
+                            glyph_data.pointer,
+                            (FT_ULong)glyph_data.length );
 
       loader->stream = &inc_stream;
     }
@@ -1502,7 +1518,7 @@
 
       error = face->access_glyph_frame( loader, glyph_index,
                                         loader->glyf_offset + offset,
-                                        loader->byte_len );
+                                        (FT_UInt)loader->byte_len );
       if ( error )
         goto Exit;
 
@@ -1540,7 +1556,7 @@
 
       /* must initialize points before (possibly) overriding */
       /* glyph metrics from the incremental interface        */
-      TT_LOADER_SET_PP( loader );
+      tt_loader_set_pp( loader );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       tt_get_metrics_incr_overrides( loader, glyph_index );
@@ -1548,28 +1564,49 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-      if ( ((TT_Face)(loader->face))->doblend )
+      if ( loader->face->doblend )
       {
+        /* a small outline structure with four elements for */
+        /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
+        FT_Vector   points[4];
+        char        tags[4]     = { 1, 1, 1, 1 };
+        short       contours[4] = { 0, 1, 2, 3 };
+        FT_Outline  outline;
+
+
+        points[0].x = loader->pp1.x;
+        points[0].y = loader->pp1.y;
+        points[1].x = loader->pp2.x;
+        points[1].y = loader->pp2.y;
+
+        points[2].x = loader->pp3.x;
+        points[2].y = loader->pp3.y;
+        points[3].x = loader->pp4.x;
+        points[3].y = loader->pp4.y;
+
+        outline.n_points   = 4;
+        outline.n_contours = 4;
+        outline.points     = points;
+        outline.tags       = tags;
+        outline.contours   = contours;
+
         /* this must be done before scaling */
-        FT_Memory  memory = loader->face->memory;
-
-
-        error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
-                                          glyph_index, &deltas, 4 );
+        error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+                                            glyph_index,
+                                            &outline,
+                                            (FT_UInt)outline.n_points );
         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->pp1.x = points[0].x;
+        loader->pp1.y = points[0].y;
+        loader->pp2.x = points[1].x;
+        loader->pp2.y = points[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 );
+        loader->pp3.x = points[2].x;
+        loader->pp3.y = points[2].y;
+        loader->pp4.x = points[3].x;
+        loader->pp4.y = points[3].y;
       }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -1594,7 +1631,7 @@
 
     /* must initialize phantom points before (possibly) overriding */
     /* glyph metrics from the incremental interface                */
-    TT_LOADER_SET_PP( loader );
+    tt_loader_set_pp( loader );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     tt_get_metrics_incr_overrides( loader, glyph_index );
@@ -1630,13 +1667,51 @@
     /* otherwise, load a composite! */
     else if ( loader->n_contours == -1 )
     {
+      FT_Memory  memory = face->root.memory;
+
       FT_UInt   start_point;
       FT_UInt   start_contour;
       FT_ULong  ins_pos;  /* position of composite instructions, if any */
 
+      FT_ListNode  node, node2;
 
-      start_point   = gloader->base.outline.n_points;
-      start_contour = gloader->base.outline.n_contours;
+
+      /*
+       * We store the glyph index directly in the `node->data' pointer,
+       * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
+       * double cast to make this portable.  Note, however, that this needs
+       * pointers with a width of at least 32 bits.
+       */
+
+
+      /* clear the nodes filled by sibling chains */
+      node = ft_list_get_node_at( &loader->composites, recurse_count );
+      for ( node2 = node; node2; node2 = node2->next )
+        node2->data = (void*)ULONG_MAX;
+
+      /* check whether we already have a composite glyph with this index */
+      if ( FT_List_Find( &loader->composites,
+                         (void*)(unsigned long)glyph_index ) )
+      {
+        FT_TRACE1(( "TT_Load_Composite_Glyph:"
+                    " infinite recursion detected\n" ));
+        error = FT_THROW( Invalid_Composite );
+        goto Exit;
+      }
+
+      else if ( node )
+        node->data = (void*)(unsigned long)glyph_index;
+
+      else
+      {
+        if ( FT_NEW( node ) )
+          goto Exit;
+        node->data = (void*)(unsigned long)glyph_index;
+        FT_List_Add( &loader->composites, node );
+      }
+
+      start_point   = (FT_UInt)gloader->base.outline.n_points;
+      start_contour = (FT_UInt)gloader->base.outline.n_contours;
 
       /* for each subglyph, read composite header */
       error = face->read_composite_glyph( loader );
@@ -1654,47 +1729,108 @@
 
       if ( face->doblend )
       {
-        FT_Int       i, limit;
+        short        i, limit;
         FT_SubGlyph  subglyph;
-        FT_Memory    memory = face->root.memory;
+
+        FT_Outline  outline;
+        FT_Vector*  points   = NULL;
+        char*       tags     = NULL;
+        short*      contours = NULL;
 
 
-        /* this provides additional offsets */
-        /* for each component's translation */
+        limit = (short)gloader->current.num_subglyphs;
 
-        if ( ( error = TT_Vary_Get_Glyph_Deltas(
+        /* construct an outline structure for              */
+        /* communication with `TT_Vary_Apply_Glyph_Deltas' */
+        outline.n_points   = (short)( gloader->current.num_subglyphs + 4 );
+        outline.n_contours = outline.n_points;
+
+        outline.points   = NULL;
+        outline.tags     = NULL;
+        outline.contours = NULL;
+
+        if ( FT_NEW_ARRAY( points, outline.n_points )   ||
+             FT_NEW_ARRAY( tags, outline.n_points )     ||
+             FT_NEW_ARRAY( contours, outline.n_points ) )
+          goto Exit1;
+
+        subglyph = gloader->current.subglyphs;
+
+        for ( i = 0; i < limit; i++, subglyph++ )
+        {
+          /* applying deltas for anchor points doesn't make sense, */
+          /* but we don't have to specially check this since       */
+          /* unused delta values are zero anyways                  */
+          points[i].x = subglyph->arg1;
+          points[i].y = subglyph->arg2;
+          tags[i]     = 1;
+          contours[i] = i;
+        }
+
+        points[i].x = loader->pp1.x;
+        points[i].y = loader->pp1.y;
+        tags[i]     = 1;
+        contours[i] = i;
+
+        i++;
+        points[i].x = loader->pp2.x;
+        points[i].y = loader->pp2.y;
+        tags[i]     = 1;
+        contours[i] = i;
+
+        i++;
+        points[i].x = loader->pp3.x;
+        points[i].y = loader->pp3.y;
+        tags[i]     = 1;
+        contours[i] = i;
+
+        i++;
+        points[i].x = loader->pp4.x;
+        points[i].y = loader->pp4.y;
+        tags[i]     = 1;
+        contours[i] = i;
+
+        outline.points   = points;
+        outline.tags     = tags;
+        outline.contours = contours;
+
+        /* this call provides additional offsets */
+        /* for each component's translation      */
+        if ( ( error = TT_Vary_Apply_Glyph_Deltas(
                          face,
                          glyph_index,
-                         &deltas,
-                         gloader->current.num_subglyphs + 4 ) ) != 0 )
-          goto Exit;
+                         &outline,
+                         (FT_UInt)outline.n_points ) ) != 0 )
+          goto Exit1;
 
-        subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
-        limit    = gloader->current.num_subglyphs;
+        subglyph = gloader->current.subglyphs;
 
-        for ( i = 0; i < limit; ++i, ++subglyph )
+        for ( i = 0; i < limit; i++, subglyph++ )
         {
           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
           {
-            /* XXX: overflow check for subglyph->{arg1,arg2}.   */
-            /* deltas[i].{x,y} must be within signed 16-bit,    */
-            /* but the restriction of summed delta is not clear */
-            subglyph->arg1 += (FT_Int16)deltas[i].x;
-            subglyph->arg2 += (FT_Int16)deltas[i].y;
+            subglyph->arg1 = (FT_Int16)points[i].x;
+            subglyph->arg2 = (FT_Int16)points[i].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->pp1.x = points[i + 0].x;
+        loader->pp1.y = points[i + 0].y;
+        loader->pp2.x = points[i + 1].x;
+        loader->pp2.y = points[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->pp3.x = points[i + 2].x;
+        loader->pp3.y = points[i + 2].y;
+        loader->pp4.x = points[i + 3].x;
+        loader->pp4.y = points[i + 3].y;
 
-        FT_FREE( deltas );
+      Exit1:
+        FT_FREE( outline.points );
+        FT_FREE( outline.tags );
+        FT_FREE( outline.contours );
+
+        if ( error )
+          goto Exit;
       }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -1730,7 +1866,7 @@
 
       {
         FT_UInt      n, num_base_points;
-        FT_SubGlyph  subglyph       = 0;
+        FT_SubGlyph  subglyph       = NULL;
 
         FT_UInt      num_points     = start_point;
         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
@@ -1759,10 +1895,12 @@
           pp[2] = loader->pp3;
           pp[3] = loader->pp4;
 
-          num_base_points = gloader->base.outline.n_points;
+          num_base_points = (FT_UInt)gloader->base.outline.n_points;
 
-          error = load_truetype_glyph( loader, subglyph->index,
-                                       recurse_count + 1, FALSE );
+          error = load_truetype_glyph( loader,
+                                       (FT_UInt)subglyph->index,
+                                       recurse_count + 1,
+                                       FALSE );
           if ( error )
             goto Exit;
 
@@ -1778,7 +1916,7 @@
             loader->pp4 = pp[3];
           }
 
-          num_points = gloader->base.outline.n_points;
+          num_points = (FT_UInt)gloader->base.outline.n_points;
 
           if ( num_points == num_base_points )
             continue;
@@ -1789,8 +1927,12 @@
           /* (1): exists from the beginning                               */
           /* (2): components that have been loaded so far                 */
           /* (3): the newly loaded component                              */
-          TT_Process_Composite_Component( loader, subglyph, start_point,
-                                          num_base_points );
+          error = TT_Process_Composite_Component( loader,
+                                                  subglyph,
+                                                  start_point,
+                                                  num_base_points );
+          if ( error )
+            goto Exit;
         }
 
         loader->stream   = old_stream;
@@ -1799,16 +1941,17 @@
         /* process the glyph */
         loader->ins_pos = ins_pos;
         if ( IS_HINTED( loader->load_flags ) &&
-
 #ifdef TT_USE_BYTECODE_INTERPRETER
-
              subglyph->flags & WE_HAVE_INSTR &&
-
 #endif
-
              num_points > start_point )
-          TT_Process_Composite_Glyph( loader, start_point, start_contour );
-
+        {
+          error = TT_Process_Composite_Glyph( loader,
+                                              start_point,
+                                              start_contour );
+          if ( error )
+            goto Exit;
+        }
       }
     }
     else
@@ -1844,15 +1987,16 @@
   compute_glyph_metrics( TT_Loader  loader,
                          FT_UInt    glyph_index )
   {
-    TT_Face    face   = (TT_Face)loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Face    face   = loader->face;
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
     FT_BBox       bbox;
     FT_Fixed      y_scale;
     TT_GlyphSlot  glyph = loader->glyph;
-    TT_Size       size  = (TT_Size)loader->size;
+    TT_Size       size  = loader->size;
 
 
     y_scale = 0x10000L;
@@ -1872,9 +2016,18 @@
     glyph->metrics.horiBearingY = bbox.yMax;
     glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
 
-    /* adjust advance width to the value contained in the hdmx table */
-    if ( !face->postscript.isFixedPitch  &&
-         IS_HINTED( loader->load_flags ) )
+    /* Adjust advance width to the value contained in the hdmx table    */
+    /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */
+    /* mode of the v40 interpreter is active.  See `ttinterp.h' for     */
+    /* details on backwards compatibility mode.                         */
+    if (
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+         !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+            ( loader->exec && loader->exec->backwards_compatibility  ) ) &&
+#endif
+         !face->postscript.isFixedPitch                                  &&
+         IS_HINTED( loader->load_flags )                                 &&
+         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )               )
     {
       FT_Byte*  widthp;
 
@@ -1883,7 +2036,7 @@
                                            size->root.metrics.x_ppem,
                                            glyph_index );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
@@ -1897,15 +2050,15 @@
              ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
                 !ignore_x_mode                                      ||
                 SPH_OPTION_BITMAP_WIDTHS                            ) )
-          glyph->metrics.horiAdvance = *widthp << 6;
+          glyph->metrics.horiAdvance = *widthp * 64;
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         if ( widthp )
-          glyph->metrics.horiAdvance = *widthp << 6;
+          glyph->metrics.horiAdvance = *widthp * 64;
       }
     }
 
@@ -2036,7 +2189,7 @@
     error = sfnt->load_sbit_image( face,
                                    size->strike_index,
                                    glyph_index,
-                                   (FT_Int)load_flags,
+                                   (FT_UInt)load_flags,
                                    stream,
                                    &glyph->bitmap,
                                    &metrics );
@@ -2045,16 +2198,16 @@
       glyph->outline.n_points   = 0;
       glyph->outline.n_contours = 0;
 
-      glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
-      glyph->metrics.height = (FT_Pos)metrics.height << 6;
+      glyph->metrics.width  = (FT_Pos)metrics.width  * 64;
+      glyph->metrics.height = (FT_Pos)metrics.height * 64;
 
-      glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
-      glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
-      glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+      glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
+      glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
+      glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  * 64;
 
-      glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
-      glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
-      glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+      glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
+      glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
+      glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  * 64;
 
       glyph->format = FT_GLYPH_FORMAT_BITMAP;
 
@@ -2083,11 +2236,17 @@
                   FT_Int32      load_flags,
                   FT_Bool       glyf_table_only )
   {
+    FT_Error  error;
+
     TT_Face    face;
     FT_Stream  stream;
 #ifdef TT_USE_BYTECODE_INTERPRETER
     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
 #endif
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
+#endif
 
 
     face   = (TT_Face)glyph->face;
@@ -2101,30 +2260,32 @@
     if ( IS_HINTED( load_flags ) && !glyf_table_only )
     {
       TT_ExecContext  exec;
-      FT_Bool         grayscale;
+      FT_Bool         grayscale = TRUE;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      FT_Bool         subpixel_hinting_lean;
+      FT_Bool         grayscale_cleartype;
+#endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
-
-      FT_Bool  subpixel = FALSE;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      FT_Bool  subpixel_hinting = FALSE;
 
 #if 0
       /* not used yet */
       FT_Bool  compatible_widths;
       FT_Bool  symmetrical_smoothing;
       FT_Bool  bgr;
+      FT_Bool  vertical_lcd;
       FT_Bool  subpixel_positioned;
+      FT_Bool  gray_cleartype;
 #endif
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       FT_Bool  reexecute = FALSE;
 
 
       if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
       {
-        FT_Error  error = tt_size_ready_bytecode( size, pedantic );
-
-
+        error = tt_size_ready_bytecode( size, pedantic );
         if ( error )
           return error;
       }
@@ -2134,42 +2295,62 @@
         return size->cvt_ready;
 
       /* query new execution context */
-      exec = size->debug ? size->context
-                         : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+      exec = size->context;
       if ( !exec )
         return FT_THROW( Could_Not_Find_Context );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+      {
+        subpixel_hinting_lean   = TRUE;
+        grayscale_cleartype     = !FT_BOOL( load_flags         &
+                                            FT_LOAD_TARGET_LCD     ||
+                                            load_flags           &
+                                            FT_LOAD_TARGET_LCD_V   );
+        exec->vertical_lcd_lean = FT_BOOL( load_flags           &
+                                           FT_LOAD_TARGET_LCD_V );
+      }
+      else
+      {
+        subpixel_hinting_lean   = FALSE;
+        grayscale_cleartype     = FALSE;
+        exec->vertical_lcd_lean = FALSE;
+      }
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
-        subpixel = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
-                              FT_RENDER_MODE_MONO               )  &&
-                            SPH_OPTION_SET_SUBPIXEL                );
+        subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
+                                      FT_RENDER_MODE_MONO               )  &&
+                                    SPH_OPTION_SET_SUBPIXEL                );
 
-        if ( subpixel )
+        if ( subpixel_hinting )
           grayscale = FALSE;
         else if ( SPH_OPTION_SET_GRAYSCALE )
         {
-          grayscale = TRUE;
-          subpixel  = FALSE;
+          grayscale        = TRUE;
+          subpixel_hinting = FALSE;
         }
         else
           grayscale = FALSE;
 
         if ( FT_IS_TRICKY( glyph->face ) )
-          subpixel = FALSE;
+          subpixel_hinting = FALSE;
 
-        exec->ignore_x_mode      = subpixel || grayscale;
+        exec->ignore_x_mode      = subpixel_hinting || 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;
 
 #if 1
         exec->compatible_widths     = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
-        exec->symmetrical_smoothing = FALSE;
+        exec->symmetrical_smoothing = TRUE;
         exec->bgr                   = FALSE;
+        exec->vertical_lcd          = FALSE;
         exec->subpixel_positioned   = TRUE;
+        exec->gray_cleartype        = FALSE;
 #else /* 0 */
         exec->compatible_widths =
           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
@@ -2180,36 +2361,49 @@
         exec->bgr =
           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
                    TT_LOAD_BGR );
+        exec->vertical_lcd =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_VERTICAL_LCD );
         exec->subpixel_positioned =
           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
                    TT_LOAD_SUBPIXEL_POSITIONED );
+        exec->gray_cleartype =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_GRAY_CLEARTYPE );
 #endif /* 0 */
 
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-      {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+        grayscale = FT_BOOL( !subpixel_hinting_lean               &&
+                             FT_LOAD_TARGET_MODE( load_flags ) !=
+                               FT_RENDER_MODE_MONO                );
+      else
+#endif
         grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
-                             FT_RENDER_MODE_MONO );
-      }
+                               FT_RENDER_MODE_MONO             );
 
-      TT_Load_Context( exec, face, size );
+      error = TT_Load_Context( exec, face, size );
+      if ( error )
+        return error;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
         /* a change from mono to subpixel rendering (and vice versa) */
         /* requires a re-execution of the CVT program                */
-        if ( subpixel != exec->subpixel )
+        if ( subpixel_hinting != exec->subpixel_hinting )
         {
           FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
                       " re-executing `prep' table\n" ));
 
-          exec->subpixel = subpixel;
-          reexecute      = TRUE;
+          exec->subpixel_hinting = subpixel_hinting;
+          reexecute              = TRUE;
         }
 
         /* a change from mono to grayscale rendering (and vice versa) */
@@ -2225,14 +2419,42 @@
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+        if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+        {
+          /* a change from mono to subpixel rendering (and vice versa) */
+          /* requires a re-execution of the CVT program                */
+          if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
+          {
+            FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+                        " re-executing `prep' table\n" ));
+
+            exec->subpixel_hinting_lean = subpixel_hinting_lean;
+            reexecute                   = TRUE;
+          }
+
+          /* a change from colored to grayscale subpixel rendering (and */
+          /* vice versa) requires a re-execution of the CVT program     */
+          if ( grayscale_cleartype != exec->grayscale_cleartype )
+          {
+            FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
+                        " re-executing `prep' table\n" ));
+
+            exec->grayscale_cleartype = grayscale_cleartype;
+            reexecute                 = TRUE;
+          }
+        }
+#endif
+
         /* a change from mono to grayscale rendering (and vice versa) */
         /* requires a re-execution of the CVT program                 */
         if ( grayscale != exec->grayscale )
         {
-          FT_TRACE4(( "tt_loader_init: grayscale change,"
+          FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
                       " re-executing `prep' table\n" ));
 
           exec->grayscale = grayscale;
@@ -2242,8 +2464,7 @@
 
       if ( reexecute )
       {
-        FT_UInt   i;
-        FT_Error  error;
+        FT_UInt  i;
 
 
         for ( i = 0; i < size->cvt_size; i++ )
@@ -2253,7 +2474,7 @@
           return error;
       }
 
-      /* see whether the cvt program has disabled hinting */
+      /* check whether the cvt program has disabled hinting */
       if ( exec->GS.instruct_control & 1 )
         load_flags |= FT_LOAD_NO_HINTING;
 
@@ -2261,6 +2482,14 @@
       if ( exec->GS.instruct_control & 2 )
         exec->GS = tt_default_graphics_state;
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      /* check whether we have a font hinted for ClearType --           */
+      /* note that this flag can also be modified in a glyph's bytecode */
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+           exec->GS.instruct_control & 4                            )
+        exec->ignore_x_mode = 0;
+#endif
+
       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
       loader->exec = exec;
       loader->instructions = exec->glyphIns;
@@ -2281,8 +2510,7 @@
 #endif
 
     {
-      FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
-
+      error = face->goto_table( face, TTAG_glyf, stream, 0 );
 
       if ( FT_ERR_EQ( error, Table_Missing ) )
         loader->glyf_offset = 0;
@@ -2305,17 +2533,30 @@
       loader->gloader = gloader;
     }
 
-    loader->load_flags = load_flags;
+    loader->load_flags = (FT_ULong)load_flags;
 
-    loader->face   = (FT_Face)face;
-    loader->size   = (FT_Size)size;
+    loader->face   = face;
+    loader->size   = size;
     loader->glyph  = (FT_GlyphSlot)glyph;
     loader->stream = stream;
 
+    loader->composites.head = NULL;
+    loader->composites.tail = NULL;
+
     return FT_Err_Ok;
   }
 
 
+  static void
+  tt_loader_done( TT_Loader  loader )
+  {
+    FT_List_Finalize( &loader->composites,
+                      NULL,
+                      loader->face->root.memory,
+                      NULL );
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -2372,16 +2613,20 @@
           /* for the bbox we need the header only */
           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
           (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
+          tt_loader_done( &loader );
           glyph->linearHoriAdvance = loader.linear;
-          glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
-                                       loader.vadvance;
+          glyph->linearVertAdvance = loader.vadvance;
 
-          /* sanity check: if `horiAdvance' in the sbit metric */
-          /* structure isn't set, use `linearHoriAdvance'      */
+          /* sanity checks: if `xxxAdvance' in the sbit metric */
+          /* structure isn't set, use `linearXXXAdvance'      */
           if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
             glyph->metrics.horiAdvance =
               FT_MulFix( glyph->linearHoriAdvance,
                          size->root.metrics.x_scale );
+          if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
+            glyph->metrics.vertAdvance =
+              FT_MulFix( glyph->linearVertAdvance,
+                         size->root.metrics.y_scale );
         }
 
         return FT_Err_Ok;
@@ -2461,9 +2706,11 @@
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
 
-      compute_glyph_metrics( &loader, glyph_index );
+      error = compute_glyph_metrics( &loader, glyph_index );
     }
 
+    tt_loader_done( &loader );
+
     /* Set the `high precision' bit flag.                           */
     /* This is _critical_ to get correct output for monochrome      */
     /* TrueType glyphs at all sizes using the bytecode interpreter. */
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 3f1699e..bfa29e4 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2006, 2008, 2011 by                                     */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTGLOAD_H__
-#define __TTGLOAD_H__
+#ifndef TTGLOAD_H_
+#define TTGLOAD_H_
 
 
 #include <ft2build.h>
@@ -56,7 +56,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTGLOAD_H__ */
+#endif /* TTGLOAD_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 7899d36..c0d013c 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader                                    */
 /*                                                                         */
-/*  Copyright 2004-2013 by                                                 */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,7 +20,7 @@
   /*                                                                       */
   /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at      */
   /*                                                                       */
-  /*   http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html  */
+  /*   https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */
   /*                                                                       */
   /* The documentation for `fvar' is inconsistent.  At one point it says   */
   /* that `countSizePairs' should be 3, at another point 2.  It should     */
@@ -60,9 +60,9 @@
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
 
-#define FT_Stream_FTell( stream )  \
+#define FT_Stream_FTell( stream )                         \
           (FT_ULong)( (stream)->cursor - (stream)->base )
-#define FT_Stream_SeekSet( stream, off ) \
+#define FT_Stream_SeekSet( stream, off )                  \
           ( (stream)->cursor = (stream)->base + (off) )
 
 
@@ -96,8 +96,8 @@
 #define ALL_POINTS  (FT_UShort*)~(FT_PtrDist)0
 
 
-#define GX_PT_POINTS_ARE_WORDS      0x80
-#define GX_PT_POINT_RUN_COUNT_MASK  0x7F
+#define GX_PT_POINTS_ARE_WORDS      0x80U
+#define GX_PT_POINT_RUN_COUNT_MASK  0x7FU
 
 
   /*************************************************************************/
@@ -112,6 +112,8 @@
   /* <Input>                                                               */
   /*    stream    :: The data stream.                                      */
   /*                                                                       */
+  /*    size      :: The size of the table holding the data.               */
+  /*                                                                       */
   /* <Output>                                                              */
   /*    point_cnt :: The number of points read.  A zero value means that   */
   /*                 all points in the glyph will be affected, without     */
@@ -123,69 +125,89 @@
   /*                                                                       */
   static FT_UShort*
   ft_var_readpackedpoints( FT_Stream  stream,
+                           FT_ULong   size,
                            FT_UInt   *point_cnt )
   {
     FT_UShort *points = NULL;
-    FT_Int     n;
-    FT_Int     runcnt;
-    FT_Int     i;
-    FT_Int     j;
-    FT_Int     first;
+    FT_UInt    n;
+    FT_UInt    runcnt;
+    FT_UInt    i, j;
+    FT_UShort  first;
     FT_Memory  memory = stream->memory;
     FT_Error   error  = FT_Err_Ok;
 
     FT_UNUSED( error );
 
 
-    *point_cnt = n = FT_GET_BYTE();
+    *point_cnt = 0;
+
+    n = FT_GET_BYTE();
     if ( n == 0 )
       return ALL_POINTS;
 
     if ( n & GX_PT_POINTS_ARE_WORDS )
-      n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );
+    {
+      n  &= GX_PT_POINT_RUN_COUNT_MASK;
+      n <<= 8;
+      n  |= FT_GET_BYTE();
+    }
 
-    if ( FT_NEW_ARRAY( points, n ) )
+    if ( n > size )
+    {
+      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
+      return NULL;
+    }
+
+    /* in the nested loops below we increase `i' twice; */
+    /* it is faster to simply allocate one more slot    */
+    /* than to add another test within the loop         */
+    if ( FT_NEW_ARRAY( points, n + 1 ) )
       return NULL;
 
-    i = 0;
+    *point_cnt = n;
+
+    first = 0;
+    i     = 0;
     while ( i < n )
     {
       runcnt = FT_GET_BYTE();
       if ( runcnt & GX_PT_POINTS_ARE_WORDS )
       {
-        runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
-        first  = points[i++] = FT_GET_USHORT();
+        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
+        first      += FT_GET_USHORT();
+        points[i++] = first;
 
-        if ( runcnt < 1 || i + runcnt >= n )
-          goto Exit;
-
-        /* first point not included in runcount */
-        for ( j = 0; j < runcnt; ++j )
-          points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
+        /* first point not included in run count */
+        for ( j = 0; j < runcnt; j++ )
+        {
+          first      += FT_GET_USHORT();
+          points[i++] = first;
+          if ( i >= n )
+            break;
+        }
       }
       else
       {
-        first = points[i++] = FT_GET_BYTE();
+        first      += FT_GET_BYTE();
+        points[i++] = first;
 
-        if ( runcnt < 1 || i + runcnt >= n )
-          goto Exit;
-
-        for ( j = 0; j < runcnt; ++j )
-          points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
+        for ( j = 0; j < runcnt; j++ )
+        {
+          first      += FT_GET_BYTE();
+          points[i++] = first;
+          if ( i >= n )
+            break;
+        }
       }
     }
 
-  Exit:
     return points;
   }
 
 
-  enum
-  {
-    GX_DT_DELTAS_ARE_ZERO      = 0x80,
-    GX_DT_DELTAS_ARE_WORDS     = 0x40,
-    GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
-  };
+#define GX_DT_DELTAS_ARE_ZERO       0x80U
+#define GX_DT_DELTAS_ARE_WORDS      0x40U
+#define GX_DT_DELTA_RUN_COUNT_MASK  0x3FU
 
 
   /*************************************************************************/
@@ -200,7 +222,9 @@
   /* <Input>                                                               */
   /*    stream    :: The data stream.                                      */
   /*                                                                       */
-  /*    delta_cnt :: The number of to be read.                             */
+  /*    size      :: The size of the table holding the data.               */
+  /*                                                                       */
+  /*    delta_cnt :: The number of deltas to be read.                      */
   /*                                                                       */
   /* <Return>                                                              */
   /*    An array of FT_Short containing the deltas for the affected        */
@@ -210,18 +234,24 @@
   /*                                                                       */
   static FT_Short*
   ft_var_readpackeddeltas( FT_Stream  stream,
-                           FT_Offset  delta_cnt )
+                           FT_ULong   size,
+                           FT_UInt    delta_cnt )
   {
     FT_Short  *deltas = NULL;
-    FT_UInt    runcnt;
-    FT_Offset  i;
-    FT_UInt    j;
+    FT_UInt    runcnt, cnt;
+    FT_UInt    i, j;
     FT_Memory  memory = stream->memory;
     FT_Error   error  = FT_Err_Ok;
 
     FT_UNUSED( error );
 
 
+    if ( delta_cnt > size )
+    {
+      FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
+      return NULL;
+    }
+
     if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
       return NULL;
 
@@ -229,34 +259,30 @@
     while ( i < delta_cnt )
     {
       runcnt = FT_GET_BYTE();
+      cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
+
       if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
       {
-        /* runcnt zeroes get added */
-        for ( j = 0;
-              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
-              ++j )
+        /* `runcnt' zeroes get added */
+        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = 0;
       }
       else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
       {
-        /* runcnt shorts from the stack */
-        for ( j = 0;
-              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
-              ++j )
+        /* `runcnt' shorts from the stack */
+        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = FT_GET_SHORT();
       }
       else
       {
-        /* runcnt signed bytes from the stack */
-        for ( j = 0;
-              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
-              ++j )
+        /* `runcnt' signed bytes from the stack */
+        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = FT_GET_CHAR();
       }
 
-      if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )
+      if ( j <= cnt )
       {
-        /* Bad format */
+        /* bad format */
         FT_FREE( deltas );
         return NULL;
       }
@@ -281,12 +307,12 @@
   static void
   ft_var_load_avar( TT_Face  face )
   {
-    FT_Stream       stream = FT_FACE_STREAM(face);
+    FT_Stream       stream = FT_FACE_STREAM( face );
     FT_Memory       memory = stream->memory;
     GX_Blend        blend  = face->blend;
     GX_AVarSegment  segment;
     FT_Error        error = FT_Err_Ok;
-    FT_ULong        version;
+    FT_Long         version;
     FT_Long         axisCount;
     FT_Int          i, j;
     FT_ULong        table_len;
@@ -294,9 +320,15 @@
     FT_UNUSED( error );
 
 
+    FT_TRACE2(( "AVAR " ));
+
     blend->avar_checked = TRUE;
-    if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )
+    error = face->goto_table( face, TTAG_avar, stream, &table_len );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing\n" ));
       return;
+    }
 
     if ( FT_FRAME_ENTER( table_len ) )
       return;
@@ -304,23 +336,37 @@
     version   = FT_GET_LONG();
     axisCount = FT_GET_LONG();
 
-    if ( version != 0x00010000L                       ||
-         axisCount != (FT_Long)blend->mmvar->num_axis )
+    if ( version != 0x00010000L )
+    {
+      FT_TRACE2(( "bad table version\n" ));
       goto Exit;
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+    if ( axisCount != (FT_Long)blend->mmvar->num_axis )
+    {
+      FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n"
+                  "                  table are different\n" ));
+      goto Exit;
+    }
 
     if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
       goto Exit;
 
     segment = &blend->avar_segment[0];
-    for ( i = 0; i < axisCount; ++i, ++segment )
+    for ( i = 0; i < axisCount; i++, segment++ )
     {
+      FT_TRACE5(( "  axis %d:\n", i ));
+
       segment->pairCount = FT_GET_USHORT();
-      if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
+      if ( (FT_ULong)segment->pairCount * 4 > table_len                ||
+           FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
       {
         /* Failure.  Free everything we have done so far.  We must do */
         /* it right now since loading the `avar' table is optional.   */
 
-        for ( j = i - 1; j >= 0; --j )
+        for ( j = i - 1; j >= 0; j-- )
           FT_FREE( blend->avar_segment[j].correspondence );
 
         FT_FREE( blend->avar_segment );
@@ -328,13 +374,18 @@
         goto Exit;
       }
 
-      for ( j = 0; j < segment->pairCount; ++j )
+      for ( j = 0; j < segment->pairCount; j++ )
       {
-        segment->correspondence[j].fromCoord =
-          FT_GET_SHORT() << 2;    /* convert to Fixed */
-        segment->correspondence[j].toCoord =
-          FT_GET_SHORT()<<2;    /* convert to Fixed */
+        /* convert to Fixed */
+        segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
+        segment->correspondence[j].toCoord   = FT_GET_SHORT() * 4;
+
+        FT_TRACE5(( "    mapping %.4f to %.4f\n",
+                    segment->correspondence[j].fromCoord / 65536.0,
+                    segment->correspondence[j].toCoord / 65536.0 ));
       }
+
+      FT_TRACE5(( "\n" ));
     }
 
   Exit:
@@ -361,8 +412,8 @@
   /*    ft_var_load_gvar                                                   */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Parses the `gvar' table if present.  If `fvar' is there, `gvar'    */
-  /*    had better be there too.                                           */
+  /*    Parse the `gvar' table if present.  If `fvar' is there, `gvar' had */
+  /*    better be there too.                                               */
   /*                                                                       */
   /* <InOut>                                                               */
   /*    face :: The font face.                                             */
@@ -373,7 +424,7 @@
   static FT_Error
   ft_var_load_gvar( TT_Face  face )
   {
-    FT_Stream     stream = FT_FACE_STREAM(face);
+    FT_Stream     stream = FT_FACE_STREAM( face );
     FT_Memory     memory = stream->memory;
     GX_Blend      blend  = face->blend;
     FT_Error      error;
@@ -400,23 +451,66 @@
       FT_FRAME_END
     };
 
-    if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )
+
+    FT_TRACE2(( "GVAR " ));
+
+    if ( ( error = face->goto_table( face,
+                                     TTAG_gvar,
+                                     stream,
+                                     &table_len ) ) != 0 )
+    {
+      FT_TRACE2(( "is missing\n" ));
       goto Exit;
+    }
 
     gvar_start = FT_STREAM_POS( );
     if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
       goto Exit;
 
+    if ( gvar_head.version != 0x00010000L )
+    {
+      FT_TRACE1(( "bad table version\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
+    {
+      FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
+                  "                  table are different\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    /* rough sanity check, ignoring offsets */
+    if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
+           table_len / 2 )
+    {
+      FT_TRACE1(( "ft_var_load_gvar:"
+                  " invalid number of global coordinates\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    /* rough sanity check: offsets can be either 2 or 4 bytes, */
+    /* and a single variation needs at least 4 bytes per glyph */
+    if ( (FT_ULong)gvar_head.glyphCount *
+           ( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len )
+    {
+      FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+    blend->gvar_size   = table_len;
     blend->tuplecount  = gvar_head.globalCoordCount;
     blend->gv_glyphcnt = gvar_head.glyphCount;
     offsetToData       = gvar_start + gvar_head.offsetToData;
 
-    if ( gvar_head.version   != (FT_Long)0x00010000L              ||
-         gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
-    {
-      error = FT_THROW( Invalid_Table );
-      goto Exit;
-    }
+    FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
+                blend->tuplecount ));
 
     if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
       goto Exit;
@@ -427,8 +521,8 @@
       if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
         goto Exit;
 
-      for ( i = 0; i <= blend->gv_glyphcnt; ++i )
-        blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();
+      for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+        blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
 
       FT_FRAME_EXIT();
     }
@@ -438,9 +532,9 @@
       if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
         goto Exit;
 
-      for ( i = 0; i <= blend->gv_glyphcnt; ++i )
+      for ( i = 0; i <= blend->gv_glyphcnt; i++ )
         blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
-                                              /* XXX: Undocumented: `*2'! */
+                                               /* XXX: Undocumented: `*2'! */
 
       FT_FRAME_EXIT();
     }
@@ -451,14 +545,24 @@
                          gvar_head.axisCount * blend->tuplecount ) )
         goto Exit;
 
-      if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord )       ||
-           FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L )                   )
+      if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord )         ||
+           FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
         goto Exit;
 
-      for ( i = 0; i < blend->tuplecount; ++i )
-        for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j )
+      for ( i = 0; i < blend->tuplecount; i++ )
+      {
+        FT_TRACE5(( "  [ " ));
+        for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
+        {
           blend->tuplecoords[i * gvar_head.axisCount + j] =
-            FT_GET_SHORT() << 2;                /* convert to FT_Fixed */
+            FT_GET_SHORT() * 4;                 /* convert to FT_Fixed */
+          FT_TRACE5(( "%.4f ",
+            blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
+        }
+        FT_TRACE5(( "]\n" ));
+      }
+
+      FT_TRACE5(( "\n" ));
 
       FT_FRAME_EXIT();
     }
@@ -506,48 +610,100 @@
     FT_Fixed  apply = 0x10000L;
 
 
-    for ( i = 0; i < blend->num_axis; ++i )
+    for ( i = 0; i < blend->num_axis; i++ )
     {
+      FT_TRACE6(( "    axis coordinate %d (%.4f):\n",
+                  i, blend->normalizedcoords[i] / 65536.0 ));
+      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+        FT_TRACE6(( "      intermediate coordinates %d (%.4f, %.4f):\n",
+                    i,
+                    im_start_coords[i] / 65536.0,
+                    im_end_coords[i] / 65536.0 ));
+
+      /* It's not clear why (for intermediate tuples) we don't need     */
+      /* to check against start/end -- the documentation says we don't. */
+      /* Similarly, it's unclear why we don't need to scale along the   */
+      /* axis.                                                          */
+
       if ( tuple_coords[i] == 0 )
-        /* It's not clear why (for intermediate tuples) we don't need     */
-        /* to check against start/end -- the documentation says we don't. */
-        /* Similarly, it's unclear why we don't need to scale along the   */
-        /* axis.                                                          */
+      {
+        FT_TRACE6(( "      tuple coordinate is zero, ignored\n", i ));
         continue;
+      }
 
-      else if ( blend->normalizedcoords[i] == 0                           ||
-                ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
-                ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
+      if ( blend->normalizedcoords[i] == 0 )
       {
+        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
         apply = 0;
         break;
       }
 
-      else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+      if ( blend->normalizedcoords[i] == tuple_coords[i] )
+      {
+        FT_TRACE6(( "      tuple coordinate value %.4f fits perfectly\n",
+                    tuple_coords[i] / 65536.0 ));
+        /* `apply' does not change */
+        continue;
+      }
+
+      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+      {
         /* not an intermediate tuple */
-        apply = FT_MulFix( apply,
-                           blend->normalizedcoords[i] > 0
-                             ? blend->normalizedcoords[i]
-                             : -blend->normalizedcoords[i] );
 
-      else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
-                blend->normalizedcoords[i] >= im_end_coords[i]   )
-      {
-        apply = 0;
-        break;
+        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
+             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
+        {
+          FT_TRACE6(( "      tuple coordinate value %.4f is exceeded, stop\n",
+                      tuple_coords[i] / 65536.0 ));
+          apply = 0;
+          break;
+        }
+
+        FT_TRACE6(( "      tuple coordinate value %.4f fits\n",
+                    tuple_coords[i] / 65536.0 ));
+        apply = FT_MulDiv( apply,
+                           blend->normalizedcoords[i],
+                           tuple_coords[i] );
       }
-
-      else if ( blend->normalizedcoords[i] < tuple_coords[i] )
-        apply = FT_MulDiv( apply,
-                           blend->normalizedcoords[i] - im_start_coords[i],
-                           tuple_coords[i] - im_start_coords[i] );
-
       else
-        apply = FT_MulDiv( apply,
-                           im_end_coords[i] - blend->normalizedcoords[i],
-                           im_end_coords[i] - tuple_coords[i] );
+      {
+        /* intermediate tuple */
+
+        if ( blend->normalizedcoords[i] < im_start_coords[i] ||
+             blend->normalizedcoords[i] > im_end_coords[i]   )
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] is exceeded,"
+                      " stop\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = 0;
+          break;
+        }
+
+        else if ( blend->normalizedcoords[i] < tuple_coords[i] )
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = FT_MulDiv( apply,
+                             blend->normalizedcoords[i] - im_start_coords[i],
+                             tuple_coords[i] - im_start_coords[i] );
+        }
+
+        else
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = FT_MulDiv( apply,
+                             im_end_coords[i] - blend->normalizedcoords[i],
+                             im_end_coords[i] - tuple_coords[i] );
+        }
+      }
     }
 
+    FT_TRACE6(( "    apply factor is %.4f\n", apply / 65536.0 ));
+
     return apply;
   }
 
@@ -577,9 +733,9 @@
   typedef struct  fvar_axis_
   {
     FT_ULong   axisTag;
-    FT_ULong   minValue;
-    FT_ULong   defaultValue;
-    FT_ULong   maxValue;
+    FT_Fixed   minValue;
+    FT_Fixed   defaultValue;
+    FT_Fixed   maxValue;
     FT_UShort  flags;
     FT_UShort  nameID;
 
@@ -600,7 +756,8 @@
   /*              TT_Get_MM_Var initializes the blend structure.           */
   /*                                                                       */
   /* <Output>                                                              */
-  /*    master :: The `fvar' data (must be freed by caller).               */
+  /*    master :: The `fvar' data (must be freed by caller).  Can be NULL, */
+  /*              which makes this function simply load MM support.        */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
@@ -647,25 +804,37 @@
 
       FT_FRAME_START( 20 ),
         FT_FRAME_ULONG ( axisTag ),
-        FT_FRAME_ULONG ( minValue ),
-        FT_FRAME_ULONG ( defaultValue ),
-        FT_FRAME_ULONG ( maxValue ),
+        FT_FRAME_LONG  ( minValue ),
+        FT_FRAME_LONG  ( defaultValue ),
+        FT_FRAME_LONG  ( maxValue ),
         FT_FRAME_USHORT( flags ),
         FT_FRAME_USHORT( nameID ),
       FT_FRAME_END
     };
 
 
+    /* read the font data and set up the internal representation */
+    /* if not already done                                       */
+
     if ( face->blend == NULL )
     {
-      /* both `fvar' and `gvar' must be present */
-      if ( (error = face->goto_table( face, TTAG_gvar,
-                                      stream, &table_len )) != 0 )
-        goto Exit;
+      FT_TRACE2(( "FVAR " ));
 
-      if ( (error = face->goto_table( face, TTAG_fvar,
-                                      stream, &table_len )) != 0 )
+      /* both `fvar' and `gvar' must be present */
+      if ( ( error = face->goto_table( face, TTAG_gvar,
+                                       stream, &table_len ) ) != 0 )
+      {
+        FT_TRACE1(( "\n"
+                    "TT_Get_MM_Var: `gvar' table is missing\n" ));
         goto Exit;
+      }
+
+      if ( ( error = face->goto_table( face, TTAG_fvar,
+                                       stream, &table_len ) ) != 0 )
+      {
+        FT_TRACE1(( "is missing\n" ));
+        goto Exit;
+      }
 
       fvar_start = FT_STREAM_POS( );
 
@@ -673,7 +842,12 @@
         goto Exit;
 
       if ( fvar_head.version != (FT_Long)0x00010000L                      ||
+#if 0
+           /* fonts like `JamRegular.ttf' have an incorrect value for */
+           /* `countSizePairs'; since value 2 is hard-coded in `fvar' */
+           /* version 1.0, we simply ignore it                        */
            fvar_head.countSizePairs != 2                                  ||
+#endif
            fvar_head.axisSize != 20                                       ||
            /* axisCount limit implied by 16-bit instanceSize */
            fvar_head.axisCount > 0x3FFE                                   ||
@@ -683,10 +857,16 @@
            fvar_head.offsetToData + fvar_head.axisCount * 20U +
              fvar_head.instanceCount * fvar_head.instanceSize > table_len )
       {
+        FT_TRACE1(( "\n"
+                    "TT_Get_MM_Var: invalid `fvar' header\n" ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
       }
 
+      FT_TRACE2(( "loaded\n" ));
+
+      FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
+
       if ( FT_NEW( face->blend ) )
         goto Exit;
 
@@ -702,6 +882,9 @@
         goto Exit;
       face->blend->mmvar = mmvar;
 
+      /* set up pointers and offsets into the `mmvar' array; */
+      /* the data gets filled in later on                    */
+
       mmvar->num_axis =
         fvar_head.axisCount;
       mmvar->num_designs =
@@ -711,30 +894,32 @@
       mmvar->num_namedstyles =
         fvar_head.instanceCount;
       mmvar->axis =
-        (FT_Var_Axis*)&(mmvar[1]);
+        (FT_Var_Axis*)&( mmvar[1] );
       mmvar->namedstyle =
-        (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);
+        (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
 
       next_coords =
-        (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);
-      for ( i = 0; i < fvar_head.instanceCount; ++i )
+        (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] );
+      for ( i = 0; i < fvar_head.instanceCount; i++ )
       {
         mmvar->namedstyle[i].coords  = next_coords;
         next_coords                 += fvar_head.axisCount;
       }
 
       next_name = (FT_String*)next_coords;
-      for ( i = 0; i < fvar_head.axisCount; ++i )
+      for ( i = 0; i < fvar_head.axisCount; i++ )
       {
         mmvar->axis[i].name  = next_name;
         next_name           += 5;
       }
 
+      /* now fill in the data */
+
       if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
         goto Exit;
 
       a = mmvar->axis;
-      for ( i = 0; i < fvar_head.axisCount; ++i )
+      for ( i = 0; i < fvar_head.axisCount; i++ )
       {
         GX_FVar_Axis  axis_rec;
 
@@ -742,22 +927,30 @@
         if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
           goto Exit;
         a->tag     = axis_rec.axisTag;
-        a->minimum = axis_rec.minValue;     /* A Fixed */
-        a->def     = axis_rec.defaultValue; /* A Fixed */
-        a->maximum = axis_rec.maxValue;     /* A Fixed */
+        a->minimum = axis_rec.minValue;
+        a->def     = axis_rec.defaultValue;
+        a->maximum = axis_rec.maxValue;
         a->strid   = axis_rec.nameID;
 
         a->name[0] = (FT_String)(   a->tag >> 24 );
         a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
         a->name[2] = (FT_String)( ( a->tag >>  8 ) & 0xFF );
         a->name[3] = (FT_String)( ( a->tag       ) & 0xFF );
-        a->name[4] = 0;
+        a->name[4] = '\0';
 
-        ++a;
+        FT_TRACE5(( "  \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n",
+                    a->name,
+                    a->minimum / 65536.0,
+                    a->def / 65536.0,
+                    a->maximum / 65536.0 ));
+
+        a++;
       }
 
+      FT_TRACE5(( "\n" ));
+
       ns = mmvar->namedstyle;
-      for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns )
+      for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
       {
         if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
           goto Exit;
@@ -765,13 +958,15 @@
         ns->strid       =    FT_GET_USHORT();
         (void) /* flags = */ FT_GET_USHORT();
 
-        for ( j = 0; j < fvar_head.axisCount; ++j )
-          ns->coords[j] = FT_GET_ULONG();     /* A Fixed */
+        for ( j = 0; j < fvar_head.axisCount; j++ )
+          ns->coords[j] = FT_GET_LONG();
 
         FT_FRAME_EXIT();
       }
     }
 
+    /* fill the output array if requested */
+
     if ( master != NULL )
     {
       FT_UInt  n;
@@ -782,36 +977,36 @@
       FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
 
       mmvar->axis =
-        (FT_Var_Axis*)&(mmvar[1]);
+        (FT_Var_Axis*)&( mmvar[1] );
       mmvar->namedstyle =
-        (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);
+        (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
       next_coords =
-        (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);
+        (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
 
-      for ( n = 0; n < mmvar->num_namedstyles; ++n )
+      for ( n = 0; n < mmvar->num_namedstyles; n++ )
       {
         mmvar->namedstyle[n].coords  = next_coords;
         next_coords                 += mmvar->num_axis;
       }
 
-      a = mmvar->axis;
+      a         = mmvar->axis;
       next_name = (FT_String*)next_coords;
-      for ( n = 0; n < mmvar->num_axis; ++n )
+      for ( n = 0; n < mmvar->num_axis; n++ )
       {
         a->name = next_name;
 
         /* standard PostScript names for some standard apple tags */
         if ( a->tag == TTAG_wght )
-          a->name = (char *)"Weight";
+          a->name = (char*)"Weight";
         else if ( a->tag == TTAG_wdth )
-          a->name = (char *)"Width";
+          a->name = (char*)"Width";
         else if ( a->tag == TTAG_opsz )
-          a->name = (char *)"OpticalSize";
+          a->name = (char*)"OpticalSize";
         else if ( a->tag == TTAG_slnt )
-          a->name = (char *)"Slant";
+          a->name = (char*)"Slant";
 
         next_name += 5;
-        ++a;
+        a++;
       }
 
       *master = mmvar;
@@ -837,9 +1032,12 @@
   /*                  Initialize the blend structure with `gvar' data.     */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    num_coords :: Must be the axis count of the font.                  */
+  /*    num_coords :: The number of available coordinates.  If it is       */
+  /*                  larger than the number of axes, ignore the excess    */
+  /*                  values.  If it is smaller than the number of axes,   */
+  /*                  use the default value (0) for the remaining axes.    */
   /*                                                                       */
-  /*    coords     :: An array of num_coords, each between [-1,1].         */
+  /*    coords     :: An array of `num_coords', each between [-1,1].       */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
@@ -868,33 +1066,44 @@
 
     if ( face->blend == NULL )
     {
-      if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )
+      if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
         goto Exit;
     }
 
     blend = face->blend;
     mmvar = blend->mmvar;
 
-    if ( num_coords != mmvar->num_axis )
+    if ( num_coords > mmvar->num_axis )
     {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
+      FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n",
+                  mmvar->num_axis, num_coords ));
+      num_coords = mmvar->num_axis;
     }
 
-    for ( i = 0; i < num_coords; ++i )
+    FT_TRACE5(( "normalized design coordinates:\n" ));
+
+    for ( i = 0; i < num_coords; i++ )
+    {
+      FT_TRACE5(( "  %.4f\n", coords[i] / 65536.0 ));
       if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
       {
+        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n"
+                    "                 is out of range [-1;1]\n",
+                    coords[i] / 65536.0 ));
         error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
+    }
+
+    FT_TRACE5(( "\n" ));
 
     if ( blend->glyphoffsets == NULL )
-      if ( (error = ft_var_load_gvar( face )) != 0 )
+      if ( ( error = ft_var_load_gvar( face ) ) != 0 )
         goto Exit;
 
     if ( blend->normalizedcoords == NULL )
     {
-      if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )
+      if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) )
         goto Exit;
 
       manageCvt = mcvt_modify;
@@ -906,7 +1115,8 @@
     else
     {
       manageCvt = mcvt_retain;
-      for ( i = 0; i < num_coords; ++i )
+
+      for ( i = 0; i < num_coords; i++ )
       {
         if ( blend->normalizedcoords[i] != coords[i] )
         {
@@ -915,13 +1125,22 @@
         }
       }
 
+      for ( ; i < mmvar->num_axis; i++ )
+      {
+        if ( blend->normalizedcoords[i] != 0 )
+        {
+          manageCvt = mcvt_load;
+          break;
+        }
+      }
+
       /* If we don't change the blend coords then we don't need to do  */
       /* anything to the cvt table.  It will be correct.  Otherwise we */
       /* no longer have the original cvt (it was modified when we set  */
       /* the blend last time), so we must reload and then modify it.   */
     }
 
-    blend->num_axis = num_coords;
+    blend->num_axis = mmvar->num_axis;
     FT_MEM_COPY( blend->normalizedcoords,
                  coords,
                  num_coords * sizeof ( FT_Fixed ) );
@@ -938,13 +1157,13 @@
         FT_FREE( face->cvt );
         face->cvt = NULL;
 
-        tt_face_load_cvt( face, face->root.stream );
+        error = tt_face_load_cvt( face, face->root.stream );
         break;
 
       case mcvt_modify:
         /* The original cvt table is in memory.  All we need to do is */
         /* apply the `cvar' table (if any).                           */
-        tt_face_vary_cvt( face, face->root.stream );
+        error = tt_face_vary_cvt( face, face->root.stream );
         break;
 
       case mcvt_retain:
@@ -973,7 +1192,10 @@
   /*                  Initialize the blend struct with `gvar' data.        */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    num_coords :: This must be the axis count of the font.             */
+  /*    num_coords :: The number of available coordinates.  If it is       */
+  /*                  larger than the number of axes, ignore the excess    */
+  /*                  values.  If it is smaller than the number of axes,   */
+  /*                  use the default values for the remaining axes.       */
   /*                                                                       */
   /*    coords     :: A coordinate array with `num_coords' elements.       */
   /*                                                                       */
@@ -997,17 +1219,19 @@
 
     if ( face->blend == NULL )
     {
-      if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )
+      if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
         goto Exit;
     }
 
     blend = face->blend;
     mmvar = blend->mmvar;
 
-    if ( num_coords != mmvar->num_axis )
+    if ( num_coords > mmvar->num_axis )
     {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
+      FT_TRACE2(( "TT_Set_Var_Design:"
+                  " only using first %d of %d coordinates\n",
+                  mmvar->num_axis, num_coords ));
+      num_coords = mmvar->num_axis;
     }
 
     /* Axis normalization is a two stage process.  First we normalize */
@@ -1017,32 +1241,52 @@
     if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
       goto Exit;
 
+    FT_TRACE5(( "design coordinates:\n" ));
+
     a = mmvar->axis;
-    for ( i = 0; i < mmvar->num_axis; ++i, ++a )
+    for ( i = 0; i < num_coords; i++, a++ )
     {
+      FT_TRACE5(( "  %.4f\n", coords[i] / 65536.0 ));
       if ( coords[i] > a->maximum || coords[i] < a->minimum )
       {
+        FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n"
+                    "                   is out of range [%.4f;%.4f]\n",
+                    coords[i] / 65536.0,
+                    a->minimum / 65536.0,
+                    a->maximum / 65536.0 ));
         error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
 
       if ( coords[i] < a->def )
-        normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def );
+        normalized[i] = -FT_DivFix( coords[i] - a->def,
+                                    a->minimum - a->def );
       else if ( a->maximum == a->def )
         normalized[i] = 0;
       else
-        normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def );
+        normalized[i] = FT_DivFix( coords[i] - a->def,
+                                   a->maximum - a->def );
     }
 
+    FT_TRACE5(( "\n" ));
+
+    for ( ; i < mmvar->num_axis; i++ )
+      normalized[i] = 0;
+
     if ( !blend->avar_checked )
       ft_var_load_avar( face );
 
     if ( blend->avar_segment != NULL )
     {
+      FT_TRACE5(( "normalized design coordinates"
+                  " before applying `avar' data:\n" ));
+
       av = blend->avar_segment;
-      for ( i = 0; i < mmvar->num_axis; ++i, ++av )
+      for ( i = 0; i < mmvar->num_axis; i++, av++ )
       {
-        for ( j = 1; j < (FT_UInt)av->pairCount; ++j )
+        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
+        {
+          FT_TRACE5(( "  %.4f\n", normalized[i] / 65536.0 ));
           if ( normalized[i] < av->correspondence[j].fromCoord )
           {
             normalized[i] =
@@ -1054,10 +1298,11 @@
               av->correspondence[j - 1].toCoord;
             break;
           }
+        }
       }
     }
 
-    error = TT_Set_MM_Blend( face, num_coords, normalized );
+    error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized );
 
   Exit:
     FT_FREE( normalized );
@@ -1120,16 +1365,16 @@
 
     if ( blend == NULL )
     {
-      FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-
+      FT_TRACE2(( "\n"
+                  "tt_face_vary_cvt: no blend specified\n" ));
       error = FT_Err_Ok;
       goto Exit;
     }
 
     if ( face->cvt == NULL )
     {
-      FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-
+      FT_TRACE2(( "\n"
+                  "tt_face_vary_cvt: no `cvt ' table\n" ));
       error = FT_Err_Ok;
       goto Exit;
     }
@@ -1158,25 +1403,43 @@
       goto FExit;
     }
 
+    FT_TRACE2(( "loaded\n" ));
+
     if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
          FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
          FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
       goto FExit;
 
     tupleCount   = FT_GET_USHORT();
-    offsetToData = table_start + FT_GET_USHORT();
+    offsetToData = FT_GET_USHORT();
 
-    /* The documentation implies there are flags packed into the        */
-    /* tuplecount, but John Jenkins says that shared points don't apply */
-    /* to `cvar', and no other flags are defined.                       */
+    /* rough sanity test */
+    if ( offsetToData + tupleCount * 4 > table_len )
+    {
+      FT_TRACE2(( "tt_face_vary_cvt:"
+                  " invalid CVT variation array header\n" ));
 
-    for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
+      error = FT_THROW( Invalid_Table );
+      goto FExit;
+    }
+
+    offsetToData += table_start;
+
+    /* The documentation implies there are flags packed into              */
+    /* `tupleCount', but John Jenkins says that shared points don't apply */
+    /* to `cvar', and no other flags are defined.                         */
+
+    FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
+
+    for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
     {
       FT_UInt   tupleDataSize;
       FT_UInt   tupleIndex;
       FT_Fixed  apply;
 
 
+      FT_TRACE6(( "  tuple %d:\n", i ));
+
       tupleDataSize = FT_GET_USHORT();
       tupleIndex    = FT_GET_USHORT();
 
@@ -1185,8 +1448,8 @@
 
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
-        for ( j = 0; j < blend->num_axis; ++j )
-          tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from        */
+        for ( j = 0; j < blend->num_axis; j++ )
+          tuple_coords[j] = FT_GET_SHORT() * 4;  /* convert from        */
                                                  /* short frac to fixed */
       }
       else
@@ -1194,7 +1457,7 @@
         /* skip this tuple; it makes no sense */
 
         if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
-          for ( j = 0; j < 2 * blend->num_axis; ++j )
+          for ( j = 0; j < 2 * blend->num_axis; j++ )
             (void)FT_GET_SHORT();
 
         offsetToData += tupleDataSize;
@@ -1203,10 +1466,10 @@
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
-        for ( j = 0; j < blend->num_axis; ++j )
-          im_start_coords[j] = FT_GET_SHORT() << 2;
-        for ( j = 0; j < blend->num_axis; ++j )
-          im_end_coords[j] = FT_GET_SHORT() << 2;
+        for ( j = 0; j < blend->num_axis; j++ )
+          im_start_coords[j] = FT_GET_SHORT() * 4;
+        for ( j = 0; j < blend->num_axis; j++ )
+          im_end_coords[j] = FT_GET_SHORT() * 4;
       }
 
       apply = ft_var_apply_tuple( blend,
@@ -1228,30 +1491,82 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      localpoints = ft_var_readpackedpoints( stream, &point_count );
+      localpoints = ft_var_readpackedpoints( stream,
+                                             table_len,
+                                             &point_count );
       deltas      = ft_var_readpackeddeltas( stream,
+                                             table_len,
                                              point_count == 0 ? face->cvt_size
                                                               : point_count );
       if ( localpoints == NULL || deltas == NULL )
-        /* failure, ignore it */;
+        ; /* failure, ignore it */
 
       else if ( localpoints == ALL_POINTS )
       {
+#ifdef FT_DEBUG_LEVEL_TRACE
+        int  count = 0;
+#endif
+
+
+        FT_TRACE7(( "    CVT deltas:\n" ));
+
         /* this means that there are deltas for every entry in cvt */
-        for ( j = 0; j < face->cvt_size; ++j )
-          face->cvt[j] = (FT_Short)( face->cvt[j] +
+        for ( j = 0; j < face->cvt_size; j++ )
+        {
+          FT_Long  orig_cvt = face->cvt[j];
+
+
+          face->cvt[j] = (FT_Short)( orig_cvt +
                                      FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          if ( orig_cvt != face->cvt[j] )
+          {
+            FT_TRACE7(( "      %d: %d -> %d\n",
+                        j, orig_cvt, face->cvt[j] ));
+            count++;
+          }
+#endif
+        }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !count )
+          FT_TRACE7(( "      none\n" ));
+#endif
       }
 
       else
       {
-        for ( j = 0; j < point_count; ++j )
-        {
-          int  pindex = localpoints[j];
+#ifdef FT_DEBUG_LEVEL_TRACE
+        int  count = 0;
+#endif
 
-          face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
+
+        FT_TRACE7(( "    CVT deltas:\n" ));
+
+        for ( j = 0; j < point_count; j++ )
+        {
+          int      pindex   = localpoints[j];
+          FT_Long  orig_cvt = face->cvt[pindex];
+
+
+          face->cvt[pindex] = (FT_Short)( orig_cvt +
                                           FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          if ( orig_cvt != face->cvt[pindex] )
+          {
+            FT_TRACE7(( "      %d: %d -> %d\n",
+                        pindex, orig_cvt, face->cvt[pindex] ));
+            count++;
+          }
+#endif
         }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !count )
+          FT_TRACE7(( "      none\n" ));
+#endif
       }
 
       if ( localpoints != ALL_POINTS )
@@ -1263,6 +1578,8 @@
       FT_Stream_SeekSet( stream, here );
     }
 
+    FT_TRACE5(( "\n" ));
+
   FExit:
     FT_FRAME_EXIT();
 
@@ -1275,13 +1592,227 @@
   }
 
 
+  /* Shift the original coordinates of all points between indices `p1' */
+  /* and `p2', using the same difference as given by index `ref'.      */
+
+  /* modeled after `af_iup_shift' */
+
+  static void
+  tt_delta_shift( int         p1,
+                  int         p2,
+                  int         ref,
+                  FT_Vector*  in_points,
+                  FT_Vector*  out_points )
+  {
+    int        p;
+    FT_Vector  delta;
+
+
+    delta.x = out_points[ref].x - in_points[ref].x;
+    delta.y = out_points[ref].y - in_points[ref].y;
+
+    if ( delta.x == 0 && delta.y == 0 )
+      return;
+
+    for ( p = p1; p < ref; p++ )
+    {
+      out_points[p].x += delta.x;
+      out_points[p].y += delta.y;
+    }
+
+    for ( p = ref + 1; p <= p2; p++ )
+    {
+      out_points[p].x += delta.x;
+      out_points[p].y += delta.y;
+    }
+  }
+
+
+  /* Interpolate the original coordinates of all points with indices */
+  /* between `p1' and `p2', using `ref1' and `ref2' as the reference */
+  /* point indices.                                                  */
+
+  /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
+  /* `Ins_IUP'                                                     */
+
+  static void
+  tt_delta_interpolate( int         p1,
+                        int         p2,
+                        int         ref1,
+                        int         ref2,
+                        FT_Vector*  in_points,
+                        FT_Vector*  out_points )
+  {
+    int  p, i;
+
+    FT_Pos  out, in1, in2, out1, out2, d1, d2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    /* handle both horizontal and vertical coordinates */
+    for ( i = 0; i <= 1; i++ )
+    {
+      /* shift array pointers so that we can access `foo.y' as `foo.x' */
+      in_points  = (FT_Vector*)( (FT_Pos*)in_points + i );
+      out_points = (FT_Vector*)( (FT_Pos*)out_points + i );
+
+      if ( in_points[ref1].x > in_points[ref2].x )
+      {
+        p    = ref1;
+        ref1 = ref2;
+        ref2 = p;
+      }
+
+      in1  = in_points[ref1].x;
+      in2  = in_points[ref2].x;
+      out1 = out_points[ref1].x;
+      out2 = out_points[ref2].x;
+      d1   = out1 - in1;
+      d2   = out2 - in2;
+
+      if ( out1 == out2 || in1 == in2 )
+      {
+        for ( p = p1; p <= p2; p++ )
+        {
+          out = in_points[p].x;
+
+          if ( out <= in1 )
+            out += d1;
+          else if ( out >= in2 )
+            out += d2;
+          else
+            out = out1;
+
+          out_points[p].x = out;
+        }
+      }
+      else
+      {
+        FT_Fixed  scale = FT_DivFix( out2 - out1, in2 - in1 );
+
+
+        for ( p = p1; p <= p2; p++ )
+        {
+          out = in_points[p].x;
+
+          if ( out <= in1 )
+            out += d1;
+          else if ( out >= in2 )
+            out += d2;
+          else
+            out = out1 + FT_MulFix( out - in1, scale );
+
+          out_points[p].x = out;
+        }
+      }
+    }
+  }
+
+
+  /* Interpolate points without delta values, similar to */
+  /* the `IUP' hinting instruction.                      */
+
+  /* modeled after `Ins_IUP */
+
+  static void
+  tt_interpolate_deltas( FT_Outline*  outline,
+                         FT_Vector*   out_points,
+                         FT_Vector*   in_points,
+                         FT_Bool*     has_delta )
+  {
+    FT_Int  first_point;
+    FT_Int  end_point;
+
+    FT_Int  first_delta;
+    FT_Int  cur_delta;
+
+    FT_Int    point;
+    FT_Short  contour;
+
+
+    /* ignore empty outlines */
+    if ( !outline->n_contours )
+      return;
+
+    contour = 0;
+    point   = 0;
+
+    do
+    {
+      end_point   = outline->contours[contour];
+      first_point = point;
+
+      /* search first point that has a delta */
+      while ( point <= end_point && !has_delta[point] )
+        point++;
+
+      if ( point <= end_point )
+      {
+        first_delta = point;
+        cur_delta   = point;
+
+        point++;
+
+        while ( point <= end_point )
+        {
+          /* search next point that has a delta  */
+          /* and interpolate intermediate points */
+          if ( has_delta[point] )
+          {
+            tt_delta_interpolate( cur_delta + 1,
+                                  point - 1,
+                                  cur_delta,
+                                  point,
+                                  in_points,
+                                  out_points );
+            cur_delta = point;
+          }
+
+          point++;
+        }
+
+        /* shift contour if we only have a single delta */
+        if ( cur_delta == first_delta )
+          tt_delta_shift( first_point,
+                          end_point,
+                          cur_delta,
+                          in_points,
+                          out_points );
+        else
+        {
+          /* otherwise handle remaining points       */
+          /* at the end and beginning of the contour */
+          tt_delta_interpolate( cur_delta + 1,
+                                end_point,
+                                cur_delta,
+                                first_delta,
+                                in_points,
+                                out_points );
+
+          if ( first_delta > 0 )
+            tt_delta_interpolate( first_point,
+                                  first_delta - 1,
+                                  cur_delta,
+                                  first_delta,
+                                  in_points,
+                                  out_points );
+        }
+      }
+      contour++;
+
+    } while ( contour < outline->n_contours );
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    TT_Vary_Get_Glyph_Deltas                                           */
+  /*    TT_Vary_Apply_Glyph_Deltas                                         */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Load the appropriate deltas for the current glyph.                 */
+  /*    Apply the appropriate deltas to the current glyph.                 */
   /*                                                                       */
   /* <Input>                                                               */
   /*    face        :: A handle to the target face object.                 */
@@ -1291,22 +1822,25 @@
   /*    n_points    :: The number of the points in the glyph, including    */
   /*                   phantom points.                                     */
   /*                                                                       */
-  /* <Output>                                                              */
-  /*    deltas      :: The array of points to change.                      */
+  /* <InOut>                                                               */
+  /*    outline     :: The outline to change.                              */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  TT_Vary_Get_Glyph_Deltas( TT_Face      face,
-                            FT_UInt      glyph_index,
-                            FT_Vector*  *deltas,
-                            FT_UInt      n_points )
+  TT_Vary_Apply_Glyph_Deltas( TT_Face      face,
+                              FT_UInt      glyph_index,
+                              FT_Outline*  outline,
+                              FT_UInt      n_points )
   {
     FT_Stream   stream = face->root.stream;
     FT_Memory   memory = stream->memory;
     GX_Blend    blend  = face->blend;
-    FT_Vector*  delta_xy = NULL;
+
+    FT_Vector*  points_org = NULL;
+    FT_Vector*  points_out = NULL;
+    FT_Bool*    has_delta  = NULL;
 
     FT_Error    error;
     FT_ULong    glyph_start;
@@ -1327,15 +1861,19 @@
     if ( !face->doblend || blend == NULL )
       return FT_THROW( Invalid_Argument );
 
-    /* to be freed by the caller */
-    if ( FT_NEW_ARRAY( delta_xy, n_points ) )
-      goto Exit;
-    *deltas = delta_xy;
-
     if ( glyph_index >= blend->gv_glyphcnt      ||
          blend->glyphoffsets[glyph_index] ==
            blend->glyphoffsets[glyph_index + 1] )
-      return FT_Err_Ok;               /* no variation data for this glyph */
+    {
+      FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+                  " no variation data for this glyph\n" ));
+      return FT_Err_Ok;
+    }
+
+    if ( FT_NEW_ARRAY( points_org, n_points ) ||
+         FT_NEW_ARRAY( points_out, n_points ) ||
+         FT_NEW_ARRAY( has_delta, n_points )  )
+      goto Fail1;
 
     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] )   ||
          FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
@@ -1353,7 +1891,20 @@
       goto Fail2;
 
     tupleCount   = FT_GET_USHORT();
-    offsetToData = glyph_start + FT_GET_USHORT();
+    offsetToData = FT_GET_USHORT();
+
+    /* rough sanity test */
+    if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 >
+           blend->gvar_size )
+    {
+      FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+                  " invalid glyph variation array header\n" ));
+
+      error = FT_THROW( Invalid_Table );
+      goto Fail2;
+    }
+
+    offsetToData += glyph_start;
 
     if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
     {
@@ -1361,47 +1912,58 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+      sharedpoints = ft_var_readpackedpoints( stream,
+                                              blend->gvar_size,
+                                              &spoint_count );
       offsetToData = FT_Stream_FTell( stream );
 
       FT_Stream_SeekSet( stream, here );
     }
 
-    for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
+    FT_TRACE5(( "gvar: there are %d tuples:\n",
+                tupleCount & GX_TC_TUPLE_COUNT_MASK ));
+
+    for ( j = 0; j < n_points; j++ )
+      points_org[j] = outline->points[j];
+
+    for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
     {
       FT_UInt   tupleDataSize;
       FT_UInt   tupleIndex;
       FT_Fixed  apply;
 
 
+      FT_TRACE6(( "  tuple %d:\n", i ));
+
       tupleDataSize = FT_GET_USHORT();
       tupleIndex    = FT_GET_USHORT();
 
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
-        for ( j = 0; j < blend->num_axis; ++j )
-          tuple_coords[j] = FT_GET_SHORT() << 2;  /* convert from        */
+        for ( j = 0; j < blend->num_axis; j++ )
+          tuple_coords[j] = FT_GET_SHORT() * 4;   /* convert from        */
                                                   /* short frac to fixed */
       }
       else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
       {
+        FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+                    " invalid tuple index\n" ));
+
         error = FT_THROW( Invalid_Table );
-        goto Fail3;
+        goto Fail2;
       }
       else
-      {
         FT_MEM_COPY(
           tuple_coords,
-          &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
+          &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
           blend->num_axis * sizeof ( FT_Fixed ) );
-      }
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
-        for ( j = 0; j < blend->num_axis; ++j )
-          im_start_coords[j] = FT_GET_SHORT() << 2;
-        for ( j = 0; j < blend->num_axis; ++j )
-          im_end_coords[j] = FT_GET_SHORT() << 2;
+        for ( j = 0; j < blend->num_axis; j++ )
+          im_start_coords[j] = FT_GET_SHORT() * 4;
+        for ( j = 0; j < blend->num_axis; j++ )
+          im_end_coords[j] = FT_GET_SHORT() * 4;
       }
 
       apply = ft_var_apply_tuple( blend,
@@ -1418,11 +1980,13 @@
 
       here = FT_Stream_FTell( stream );
 
+      FT_Stream_SeekSet( stream, offsetToData );
+
       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
       {
-        FT_Stream_SeekSet( stream, offsetToData );
-
-        localpoints = ft_var_readpackedpoints( stream, &point_count );
+        localpoints = ft_var_readpackedpoints( stream,
+                                               blend->gvar_size,
+                                               &point_count );
         points      = localpoints;
       }
       else
@@ -1432,9 +1996,11 @@
       }
 
       deltas_x = ft_var_readpackeddeltas( stream,
+                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
       deltas_y = ft_var_readpackeddeltas( stream,
+                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
 
@@ -1443,24 +2009,108 @@
 
       else if ( points == ALL_POINTS )
       {
+#ifdef FT_DEBUG_LEVEL_TRACE
+        int  count = 0;
+#endif
+
+
+        FT_TRACE7(( "    point deltas:\n" ));
+
         /* this means that there are deltas for every point in the glyph */
-        for ( j = 0; j < n_points; ++j )
+        for ( j = 0; j < n_points; j++ )
         {
-          delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
-          delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
+          FT_Pos  delta_x = FT_MulFix( deltas_x[j], apply );
+          FT_Pos  delta_y = FT_MulFix( deltas_y[j], apply );
+
+
+          outline->points[j].x += delta_x;
+          outline->points[j].y += delta_y;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          if ( delta_x || delta_y )
+          {
+            FT_TRACE7(( "      %d: (%d, %d) -> (%d, %d)\n",
+                        j,
+                        outline->points[j].x - delta_x,
+                        outline->points[j].y - delta_y,
+                        outline->points[j].x,
+                        outline->points[j].y ));
+            count++;
+          }
+#endif
         }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !count )
+          FT_TRACE7(( "      none\n" ));
+#endif
       }
 
       else
       {
-        for ( j = 0; j < point_count; ++j )
+#ifdef FT_DEBUG_LEVEL_TRACE
+        int  count = 0;
+#endif
+
+
+        /* we have to interpolate the missing deltas similar to the */
+        /* IUP bytecode instruction                                 */
+        for ( j = 0; j < n_points; j++ )
         {
-          if ( localpoints[j] >= n_points )
+          has_delta[j]  = FALSE;
+          points_out[j] = points_org[j];
+        }
+
+        for ( j = 0; j < point_count; j++ )
+        {
+          FT_UShort  idx = points[j];
+
+
+          if ( idx >= n_points )
             continue;
 
-          delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
-          delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
+          has_delta[idx] = TRUE;
+
+          points_out[idx].x += FT_MulFix( deltas_x[j], apply );
+          points_out[idx].y += FT_MulFix( deltas_y[j], apply );
         }
+
+        /* no need to handle phantom points here,      */
+        /* since solitary points can't be interpolated */
+        tt_interpolate_deltas( outline,
+                               points_out,
+                               points_org,
+                               has_delta );
+
+        FT_TRACE7(( "    point deltas:\n" ));
+
+        for ( j = 0; j < n_points; j++ )
+        {
+          FT_Pos  delta_x = points_out[j].x - points_org[j].x;
+          FT_Pos  delta_y = points_out[j].y - points_org[j].y;
+
+
+          outline->points[j].x += delta_x;
+          outline->points[j].y += delta_y;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          if ( delta_x || delta_y )
+          {
+            FT_TRACE7(( "      %d: (%d, %d) -> (%d, %d)\n",
+                        j,
+                        outline->points[j].x - delta_x,
+                        outline->points[j].y - delta_y,
+                        outline->points[j].x,
+                        outline->points[j].y ));
+            count++;
+          }
+#endif
+        }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !count )
+          FT_TRACE7(( "      none\n" ));
+#endif
       }
 
       if ( localpoints != ALL_POINTS )
@@ -1473,22 +2123,22 @@
       FT_Stream_SeekSet( stream, here );
     }
 
-  Fail3:
+    FT_TRACE5(( "\n" ));
+
+  Fail2:
+    if ( sharedpoints != ALL_POINTS )
+      FT_FREE( sharedpoints );
     FT_FREE( tuple_coords );
     FT_FREE( im_start_coords );
     FT_FREE( im_end_coords );
 
-  Fail2:
     FT_FRAME_EXIT();
 
   Fail1:
-    if ( error )
-    {
-      FT_FREE( delta_xy );
-      *deltas = NULL;
-    }
+    FT_FREE( points_org );
+    FT_FREE( points_out );
+    FT_FREE( has_delta );
 
-  Exit:
     return error;
   }
 
@@ -1499,7 +2149,7 @@
   /*    tt_done_blend                                                      */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Frees the blend internal data structure.                           */
+  /*    Free the blend internal data structure.                            */
   /*                                                                       */
   FT_LOCAL_DEF( void )
   tt_done_blend( FT_Memory  memory,
@@ -1515,7 +2165,7 @@
 
       if ( blend->avar_segment != NULL )
       {
-        for ( i = 0; i < blend->num_axis; ++i )
+        for ( i = 0; i < blend->num_axis; i++ )
           FT_FREE( blend->avar_segment[i].correspondence );
         FT_FREE( blend->avar_segment );
       }
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 82dfc44..aa8f6ea 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader (specification)                    */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, Werner Lemberg and George Williams.      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTGXVAR_H__
-#define __TTGXVAR_H__
+#ifndef TTGXVAR_H_
+#define TTGXVAR_H_
 
 
 #include <ft2build.h>
@@ -95,6 +95,8 @@
     FT_UInt         gv_glyphcnt;
     FT_ULong*       glyphoffsets;
 
+    FT_ULong        gvar_size;
+
   } GX_BlendRec;
 
 
@@ -162,10 +164,10 @@
 
 
   FT_LOCAL( FT_Error )
-  TT_Vary_Get_Glyph_Deltas( TT_Face      face,
-                            FT_UInt      glyph_index,
-                            FT_Vector*  *deltas,
-                            FT_UInt      n_points );
+  TT_Vary_Apply_Glyph_Deltas( TT_Face      face,
+                              FT_UInt      glyph_index,
+                              FT_Outline*  outline,
+                              FT_UInt      n_points );
 
 
   FT_LOCAL( void )
@@ -176,7 +178,7 @@
 FT_END_HEADER
 
 
-#endif /* __TTGXVAR_H__ */
+#endif /* TTGXVAR_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 9491533..2d15ea7 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,8 +4,8 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2014                                                    */
-/*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
+/*  Copyright 1996-2016 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      */
@@ -26,10 +26,14 @@
 #include FT_TRIGONOMETRY_H
 #include FT_SYSTEM_H
 #include FT_TRUETYPE_DRIVER_H
+#include FT_MULTIPLE_MASTERS_H
 
 #include "ttinterp.h"
 #include "tterrors.h"
 #include "ttsubpix.h"
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.h"
+#endif
 
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
@@ -44,186 +48,34 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_ttinterp
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* In order to detect infinite loops in the code, we set up a counter    */
-  /* within the run loop.  A single stroke of interpretation is now        */
-  /* limited to a maximum number of opcodes defined below.                 */
-  /*                                                                       */
-#define MAX_RUNNABLE_OPCODES  1000000L
 
+#define NO_SUBPIXEL_HINTING                                                  \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_35 )
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* There are two kinds of implementations:                               */
-  /*                                                                       */
-  /* a. static implementation                                              */
-  /*                                                                       */
-  /*    The current execution context is a static variable, which fields   */
-  /*    are accessed directly by the interpreter during execution.  The    */
-  /*    context is named `cur'.                                            */
-  /*                                                                       */
-  /*    This version is non-reentrant, of course.                          */
-  /*                                                                       */
-  /* b. indirect implementation                                            */
-  /*                                                                       */
-  /*    The current execution context is passed to _each_ function as its  */
-  /*    first argument, and each field is thus accessed indirectly.        */
-  /*                                                                       */
-  /*    This version is fully re-entrant.                                  */
-  /*                                                                       */
-  /* The idea is that an indirect implementation may be slower to execute  */
-  /* on low-end processors that are used in some systems (like 386s or     */
-  /* even 486s).                                                           */
-  /*                                                                       */
-  /* As a consequence, the indirect implementation is now the default, as  */
-  /* its performance costs can be considered negligible in our context.    */
-  /* Note, however, that we kept the same source with macros because:      */
-  /*                                                                       */
-  /* - The code is kept very close in design to the Pascal code used for   */
-  /*   development.                                                        */
-  /*                                                                       */
-  /* - It's much more readable that way!                                   */
-  /*                                                                       */
-  /* - It's still open to experimentation and tuning.                      */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
-
-#define CUR  (*exc)                             /* see ttobjs.h */
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This macro is used whenever `exec' is unused in a function, to avoid  */
-  /* stupid warnings from pedantic compilers.                              */
-  /*                                                                       */
-#define FT_UNUSED_EXEC  FT_UNUSED( exc )
-
-#else                                           /* static implementation */
-
-#define CUR  cur
-
-#define FT_UNUSED_EXEC  int  __dummy = __dummy
-
-  static
-  TT_ExecContextRec  cur;   /* static exec. context variable */
-
-  /* apparently, we have a _lot_ of direct indexing when accessing  */
-  /* the static `cur', which makes the code bigger (due to all the  */
-  /* four bytes addresses).                                         */
-
-#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The instruction argument stack.                                       */
-  /*                                                                       */
-#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This macro is used whenever `args' is unused in a function, to avoid  */
-  /* stupid warnings from pedantic compilers.                              */
-  /*                                                                       */
-#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
-
-
-#define SUBPIXEL_HINTING                                                    \
-          ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#define SUBPIXEL_HINTING_INFINALITY                                          \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
             TT_INTERPRETER_VERSION_38 )
+#endif
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#define SUBPIXEL_HINTING_MINIMAL                                             \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_40 )
+#endif
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
-  /* increase readability of the code.                                     */
-  /*                                                                       */
-  /*************************************************************************/
+#define PROJECT( v1, v2 )                                                \
+          exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
 
+#define DUALPROJ( v1, v2 )                                                \
+          exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
 
-#define SKIP_Code() \
-          SkipCode( EXEC_ARG )
+#define FAST_PROJECT( v )                          \
+          exc->func_project( exc, (v)->x, (v)->y )
 
-#define GET_ShortIns() \
-          GetShortIns( EXEC_ARG )
-
-#define NORMalize( x, y, v ) \
-          Normalize( EXEC_ARG_ x, y, v )
-
-#define SET_SuperRound( scale, flags ) \
-          SetSuperRound( EXEC_ARG_ scale, flags )
-
-#define ROUND_None( d, c ) \
-          Round_None( EXEC_ARG_ d, c )
-
-#define INS_Goto_CodeRange( range, ip ) \
-          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
-
-#define CUR_Func_move( z, p, d ) \
-          CUR.func_move( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_move_orig( z, p, d ) \
-          CUR.func_move_orig( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_round( d, c ) \
-          CUR.func_round( EXEC_ARG_ d, c )
-
-#define CUR_Func_read_cvt( index ) \
-          CUR.func_read_cvt( EXEC_ARG_ index )
-
-#define CUR_Func_write_cvt( index, val ) \
-          CUR.func_write_cvt( EXEC_ARG_ index, val )
-
-#define CUR_Func_move_cvt( index, val ) \
-          CUR.func_move_cvt( EXEC_ARG_ index, val )
-
-#define CURRENT_Ratio() \
-          Current_Ratio( EXEC_ARG )
-
-#define CURRENT_Ppem() \
-          Current_Ppem( EXEC_ARG )
-
-#define CUR_Ppem() \
-          Cur_PPEM( EXEC_ARG )
-
-#define INS_SxVTL( a, b, c, d ) \
-          Ins_SxVTL( EXEC_ARG_ a, b, c, d )
-
-#define COMPUTE_Funcs() \
-          Compute_Funcs( EXEC_ARG )
-
-#define COMPUTE_Round( a ) \
-          Compute_Round( EXEC_ARG_ a )
-
-#define COMPUTE_Point_Displacement( a, b, c, d ) \
-          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
-
-#define MOVE_Zp2_Point( a, b, c, t ) \
-          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
-
-
-#define CUR_Func_project( v1, v2 )  \
-          CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_Func_dualproj( v1, v2 )  \
-          CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_fast_project( v ) \
-          CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
-
-#define CUR_fast_dualproj( v ) \
-          CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Instruction dispatch function, as used by the interpreter.            */
-  /*                                                                       */
-  typedef void  (*TInstruction_Function)( INS_ARG );
+#define FAST_DUALPROJ( v )                          \
+          exc->func_dualproj( exc, (v)->x, (v)->y )
 
 
   /*************************************************************************/
@@ -233,13 +85,6 @@
 #define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* This macro computes (a*2^14)/b and complements TT_MulFix14.           */
-  /*                                                                       */
-#define TT_DivFix14( a, b ) \
-          FT_DivFix( a, (b) << 2 )
-
 
 #undef  SUCCESS
 #define SUCCESS  0
@@ -247,16 +92,6 @@
 #undef  FAILURE
 #define FAILURE  1
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define GUESS_VECTOR( V )                                         \
-  if ( CUR.face->unpatented_hinting )                             \
-  {                                                               \
-    CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
-    CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
-  }
-#else
-#define GUESS_VECTOR( V )
-#endif
 
   /*************************************************************************/
   /*                                                                       */
@@ -282,10 +117,7 @@
   /* <InOut>                                                               */
   /*    exec  :: The target execution context.                             */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   TT_Goto_CodeRange( TT_ExecContext  exec,
                      FT_Int          range,
                      FT_Long         IP )
@@ -303,14 +135,12 @@
     /*       which will return to the first byte *after* the code    */
     /*       range, we test for IP <= Size instead of IP < Size.     */
     /*                                                               */
-    FT_ASSERT( (FT_ULong)IP <= coderange->size );
+    FT_ASSERT( IP <= coderange->size );
 
     exec->code     = coderange->base;
     exec->codeSize = coderange->size;
     exec->IP       = IP;
     exec->curRange = range;
-
-    return FT_Err_Ok;
   }
 
 
@@ -332,10 +162,7 @@
   /* <InOut>                                                               */
   /*    exec   :: The target execution context.                            */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   TT_Set_CodeRange( TT_ExecContext  exec,
                     FT_Int          range,
                     void*           base,
@@ -345,8 +172,6 @@
 
     exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
     exec->codeRangeTable[range - 1].size = length;
-
-    return FT_Err_Ok;
   }
 
 
@@ -364,13 +189,7 @@
   /* <InOut>                                                               */
   /*    exec  :: The target execution context.                             */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Does not set the Error variable.                                   */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   TT_Clear_CodeRange( TT_ExecContext  exec,
                       FT_Int          range )
   {
@@ -378,8 +197,6 @@
 
     exec->codeRangeTable[range - 1].base = NULL;
     exec->codeRangeTable[range - 1].size = 0;
-
-    return FT_Err_Ok;
   }
 
 
@@ -403,13 +220,10 @@
   /*                                                                       */
   /*    memory :: A handle to the parent memory object.                    */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
   /* <Note>                                                                */
   /*    Only the glyph loader and debugger should call this function.      */
   /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   TT_Done_Context( TT_ExecContext  exec )
   {
     FT_Memory  memory = exec->memory;
@@ -436,8 +250,6 @@
     exec->face = NULL;
 
     FT_FREE( exec );
-
-    return FT_Err_Ok;
   }
 
 
@@ -481,8 +293,8 @@
     exec->stackSize = 0;
     exec->glyphSize = 0;
 
-    exec->stack     = NULL;
-    exec->glyphIns  = NULL;
+    exec->stack    = NULL;
+    exec->glyphIns = NULL;
 
     exec->face = NULL;
     exec->size = NULL;
@@ -524,7 +336,7 @@
   FT_LOCAL_DEF( FT_Error )
   Update_Max( FT_Memory  memory,
               FT_ULong*  size,
-              FT_Long    multiplier,
+              FT_ULong   multiplier,
               void*      _pbuff,
               FT_ULong   new_max )
   {
@@ -588,6 +400,7 @@
       exec->maxIDefs   = size->max_instruction_defs;
       exec->FDefs      = size->function_defs;
       exec->IDefs      = size->instruction_defs;
+      exec->pointSize  = size->point_size;
       exec->tt_metrics = size->ttmetrics;
       exec->metrics    = size->metrics;
 
@@ -617,13 +430,13 @@
 
     /* XXX: We reserve a little more elements on the stack to deal safely */
     /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
-    tmp = exec->stackSize;
+    tmp = (FT_ULong)exec->stackSize;
     error = Update_Max( exec->memory,
                         &tmp,
                         sizeof ( FT_F26Dot6 ),
                         (void*)&exec->stack,
                         maxp->maxStackElements + 32 );
-    exec->stackSize = (FT_UInt)tmp;
+    exec->stackSize = (FT_Long)tmp;
     if ( error )
       return error;
 
@@ -664,13 +477,10 @@
   /* <InOut>                                                               */
   /*    size :: A handle to the target size object.                        */
   /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
   /* <Note>                                                                */
   /*    Only the glyph loader and debugger should call this function.      */
   /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL_DEF( void )
   TT_Save_Context( TT_ExecContext  exec,
                    TT_Size         size )
   {
@@ -688,8 +498,6 @@
 
     for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
       size->codeRangeTable[i] = exec->codeRangeTable[i];
-
-    return FT_Err_Ok;
   }
 
 
@@ -714,19 +522,10 @@
   /* <Return>                                                              */
   /*    TrueType error code.  0 means success.                             */
   /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  TT_Run_Context( TT_ExecContext  exec,
-                  FT_Bool         debug )
+  TT_Run_Context( TT_ExecContext  exec )
   {
-    FT_Error  error;
-
-
-    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
-           != FT_Err_Ok )
-      return error;
+    TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 );
 
     exec->zp0 = exec->pts;
     exec->zp1 = exec->pts;
@@ -742,10 +541,6 @@
     exec->GS.freeVector = exec->GS.projVector;
     exec->GS.dualVector = exec->GS.projVector;
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    exec->GS.both_x_axis = TRUE;
-#endif
-
     exec->GS.round_state = 1;
     exec->GS.loop        = 1;
 
@@ -754,16 +549,7 @@
     exec->top     = 0;
     exec->callTop = 0;
 
-#if 1
-    FT_UNUSED( debug );
-
     return exec->face->interpreter( exec );
-#else
-    if ( !debug )
-      return TT_RunIns( exec );
-    else
-      return FT_Err_Ok;
-#endif
   }
 
 
@@ -781,10 +567,6 @@
     { 0x4000, 0 },
     { 0x4000, 0 },
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    TRUE,
-#endif
-
     1, 64, 1,
     TRUE, 68, 0, 0, 9, 3,
     0, FALSE, 0, 1, 1, 1
@@ -796,29 +578,27 @@
   FT_EXPORT_DEF( TT_ExecContext )
   TT_New_Context( TT_Driver  driver )
   {
-    FT_Memory  memory = driver->root.root.memory;
+    FT_Memory  memory;
+    FT_Error   error;
+
+    TT_ExecContext  exec = NULL;
 
 
-    if ( !driver->context )
-    {
-      FT_Error        error;
-      TT_ExecContext  exec;
+    if ( !driver )
+      goto Fail;
 
+    memory = driver->root.root.memory;
 
-      /* allocate object */
-      if ( FT_NEW( exec ) )
-        goto Fail;
+    /* allocate object */
+    if ( FT_NEW( exec ) )
+      goto Fail;
 
-      /* initialize it; in case of error this deallocates `exec' too */
-      error = Init_Context( exec, memory );
-      if ( error )
-        goto Fail;
+    /* initialize it; in case of error this deallocates `exec' too */
+    error = Init_Context( exec, memory );
+    if ( error )
+      goto Fail;
 
-      /* store it into the driver */
-      driver->context = exec;
-    }
-
-    return driver->context;
+    return exec;
 
   Fail:
     return NULL;
@@ -865,8 +645,8 @@
     /*  SFvTL +   */  PACK( 2, 0 ),
     /*  SPvFS     */  PACK( 2, 0 ),
     /*  SFvFS     */  PACK( 2, 0 ),
-    /*  GPV       */  PACK( 0, 2 ),
-    /*  GFV       */  PACK( 0, 2 ),
+    /*  GPv       */  PACK( 0, 2 ),
+    /*  GFv       */  PACK( 0, 2 ),
     /*  SFvTPv    */  PACK( 0, 0 ),
     /*  ISECT     */  PACK( 5, 0 ),
 
@@ -906,17 +686,17 @@
 
     /*  IUP[0]    */  PACK( 0, 0 ),
     /*  IUP[1]    */  PACK( 0, 0 ),
-    /*  SHP[0]    */  PACK( 0, 0 ),
-    /*  SHP[1]    */  PACK( 0, 0 ),
+    /*  SHP[0]    */  PACK( 0, 0 ), /* loops */
+    /*  SHP[1]    */  PACK( 0, 0 ), /* loops */
     /*  SHC[0]    */  PACK( 1, 0 ),
     /*  SHC[1]    */  PACK( 1, 0 ),
     /*  SHZ[0]    */  PACK( 1, 0 ),
     /*  SHZ[1]    */  PACK( 1, 0 ),
-    /*  SHPIX     */  PACK( 1, 0 ),
-    /*  IP        */  PACK( 0, 0 ),
+    /*  SHPIX     */  PACK( 1, 0 ), /* loops */
+    /*  IP        */  PACK( 0, 0 ), /* loops */
     /*  MSIRP[0]  */  PACK( 2, 0 ),
     /*  MSIRP[1]  */  PACK( 2, 0 ),
-    /*  AlignRP   */  PACK( 0, 0 ),
+    /*  AlignRP   */  PACK( 0, 0 ), /* loops */
     /*  RTDG      */  PACK( 0, 0 ),
     /*  MIAP[0]   */  PACK( 2, 0 ),
     /*  MIAP[1]   */  PACK( 2, 0 ),
@@ -989,14 +769,14 @@
     /*  SANGW     */  PACK( 1, 0 ),
     /*  AA        */  PACK( 1, 0 ),
 
-    /*  FlipPT    */  PACK( 0, 0 ),
+    /*  FlipPT    */  PACK( 0, 0 ), /* loops */
     /*  FlipRgON  */  PACK( 2, 0 ),
     /*  FlipRgOFF */  PACK( 2, 0 ),
     /*  INS_$83   */  PACK( 0, 0 ),
     /*  INS_$84   */  PACK( 0, 0 ),
     /*  ScanCTRL  */  PACK( 1, 0 ),
-    /*  SDPVTL[0] */  PACK( 2, 0 ),
-    /*  SDPVTL[1] */  PACK( 2, 0 ),
+    /*  SDPvTL[0] */  PACK( 2, 0 ),
+    /*  SDPvTL[1] */  PACK( 2, 0 ),
     /*  GetINFO   */  PACK( 1, 1 ),
     /*  IDEF      */  PACK( 1, 0 ),
     /*  ROLL      */  PACK( 3, 3 ),
@@ -1007,8 +787,8 @@
     /*  INS_$8F   */  PACK( 0, 0 ),
 
     /*  INS_$90  */   PACK( 0, 0 ),
-    /*  INS_$91  */   PACK( 0, 0 ),
-    /*  INS_$92  */   PACK( 0, 0 ),
+    /*  GETVAR   */   PACK( 0, 0 ), /* will be handled specially */
+    /*  GETDATA  */   PACK( 0, 1 ),
     /*  INS_$93  */   PACK( 0, 0 ),
     /*  INS_$94  */   PACK( 0, 0 ),
     /*  INS_$95  */   PACK( 0, 0 ),
@@ -1129,280 +909,289 @@
 
 #ifdef FT_DEBUG_LEVEL_TRACE
 
+  /* the first hex digit gives the length of the opcode name; the space */
+  /* after the digit is here just to increase readability of the source */
+  /* code                                                               */
+
   static
   const char*  const opcode_name[256] =
   {
-    "SVTCA y",
-    "SVTCA x",
-    "SPvTCA y",
-    "SPvTCA x",
-    "SFvTCA y",
-    "SFvTCA x",
-    "SPvTL ||",
-    "SPvTL +",
-    "SFvTL ||",
-    "SFvTL +",
-    "SPvFS",
-    "SFvFS",
-    "GPV",
-    "GFV",
-    "SFvTPv",
-    "ISECT",
+    "7 SVTCA y",
+    "7 SVTCA x",
+    "8 SPvTCA y",
+    "8 SPvTCA x",
+    "8 SFvTCA y",
+    "8 SFvTCA x",
+    "8 SPvTL ||",
+    "7 SPvTL +",
+    "8 SFvTL ||",
+    "7 SFvTL +",
+    "5 SPvFS",
+    "5 SFvFS",
+    "3 GPv",
+    "3 GFv",
+    "6 SFvTPv",
+    "5 ISECT",
 
-    "SRP0",
-    "SRP1",
-    "SRP2",
-    "SZP0",
-    "SZP1",
-    "SZP2",
-    "SZPS",
-    "SLOOP",
-    "RTG",
-    "RTHG",
-    "SMD",
-    "ELSE",
-    "JMPR",
-    "SCvTCi",
-    "SSwCi",
-    "SSW",
+    "4 SRP0",
+    "4 SRP1",
+    "4 SRP2",
+    "4 SZP0",
+    "4 SZP1",
+    "4 SZP2",
+    "4 SZPS",
+    "5 SLOOP",
+    "3 RTG",
+    "4 RTHG",
+    "3 SMD",
+    "4 ELSE",
+    "4 JMPR",
+    "6 SCvTCi",
+    "5 SSwCi",
+    "3 SSW",
 
-    "DUP",
-    "POP",
-    "CLEAR",
-    "SWAP",
-    "DEPTH",
-    "CINDEX",
-    "MINDEX",
-    "AlignPTS",
-    "INS_$28",
-    "UTP",
-    "LOOPCALL",
-    "CALL",
-    "FDEF",
-    "ENDF",
-    "MDAP[0]",
-    "MDAP[1]",
+    "3 DUP",
+    "3 POP",
+    "5 CLEAR",
+    "4 SWAP",
+    "5 DEPTH",
+    "6 CINDEX",
+    "6 MINDEX",
+    "8 AlignPTS",
+    "7 INS_$28",
+    "3 UTP",
+    "8 LOOPCALL",
+    "4 CALL",
+    "4 FDEF",
+    "4 ENDF",
+    "7 MDAP[0]",
+    "7 MDAP[1]",
 
-    "IUP[0]",
-    "IUP[1]",
-    "SHP[0]",
-    "SHP[1]",
-    "SHC[0]",
-    "SHC[1]",
-    "SHZ[0]",
-    "SHZ[1]",
-    "SHPIX",
-    "IP",
-    "MSIRP[0]",
-    "MSIRP[1]",
-    "AlignRP",
-    "RTDG",
-    "MIAP[0]",
-    "MIAP[1]",
+    "6 IUP[0]",
+    "6 IUP[1]",
+    "6 SHP[0]",
+    "6 SHP[1]",
+    "6 SHC[0]",
+    "6 SHC[1]",
+    "6 SHZ[0]",
+    "6 SHZ[1]",
+    "5 SHPIX",
+    "2 IP",
+    "8 MSIRP[0]",
+    "8 MSIRP[1]",
+    "7 AlignRP",
+    "4 RTDG",
+    "7 MIAP[0]",
+    "7 MIAP[1]",
 
-    "NPushB",
-    "NPushW",
-    "WS",
-    "RS",
-    "WCvtP",
-    "RCvt",
-    "GC[0]",
-    "GC[1]",
-    "SCFS",
-    "MD[0]",
-    "MD[1]",
-    "MPPEM",
-    "MPS",
-    "FlipON",
-    "FlipOFF",
-    "DEBUG",
+    "6 NPushB",
+    "6 NPushW",
+    "2 WS",
+    "2 RS",
+    "5 WCvtP",
+    "4 RCvt",
+    "5 GC[0]",
+    "5 GC[1]",
+    "4 SCFS",
+    "5 MD[0]",
+    "5 MD[1]",
+    "5 MPPEM",
+    "3 MPS",
+    "6 FlipON",
+    "7 FlipOFF",
+    "5 DEBUG",
 
-    "LT",
-    "LTEQ",
-    "GT",
-    "GTEQ",
-    "EQ",
-    "NEQ",
-    "ODD",
-    "EVEN",
-    "IF",
-    "EIF",
-    "AND",
-    "OR",
-    "NOT",
-    "DeltaP1",
-    "SDB",
-    "SDS",
+    "2 LT",
+    "4 LTEQ",
+    "2 GT",
+    "4 GTEQ",
+    "2 EQ",
+    "3 NEQ",
+    "3 ODD",
+    "4 EVEN",
+    "2 IF",
+    "3 EIF",
+    "3 AND",
+    "2 OR",
+    "3 NOT",
+    "7 DeltaP1",
+    "3 SDB",
+    "3 SDS",
 
-    "ADD",
-    "SUB",
-    "DIV",
-    "MUL",
-    "ABS",
-    "NEG",
-    "FLOOR",
-    "CEILING",
-    "ROUND[0]",
-    "ROUND[1]",
-    "ROUND[2]",
-    "ROUND[3]",
-    "NROUND[0]",
-    "NROUND[1]",
-    "NROUND[2]",
-    "NROUND[3]",
+    "3 ADD",
+    "3 SUB",
+    "3 DIV",
+    "3 MUL",
+    "3 ABS",
+    "3 NEG",
+    "5 FLOOR",
+    "7 CEILING",
+    "8 ROUND[0]",
+    "8 ROUND[1]",
+    "8 ROUND[2]",
+    "8 ROUND[3]",
+    "9 NROUND[0]",
+    "9 NROUND[1]",
+    "9 NROUND[2]",
+    "9 NROUND[3]",
 
-    "WCvtF",
-    "DeltaP2",
-    "DeltaP3",
-    "DeltaCn[0]",
-    "DeltaCn[1]",
-    "DeltaCn[2]",
-    "SROUND",
-    "S45Round",
-    "JROT",
-    "JROF",
-    "ROFF",
-    "INS_$7B",
-    "RUTG",
-    "RDTG",
-    "SANGW",
-    "AA",
+    "5 WCvtF",
+    "7 DeltaP2",
+    "7 DeltaP3",
+    "A DeltaCn[0]",
+    "A DeltaCn[1]",
+    "A DeltaCn[2]",
+    "6 SROUND",
+    "8 S45Round",
+    "4 JROT",
+    "4 JROF",
+    "4 ROFF",
+    "7 INS_$7B",
+    "4 RUTG",
+    "4 RDTG",
+    "5 SANGW",
+    "2 AA",
 
-    "FlipPT",
-    "FlipRgON",
-    "FlipRgOFF",
-    "INS_$83",
-    "INS_$84",
-    "ScanCTRL",
-    "SDVPTL[0]",
-    "SDVPTL[1]",
-    "GetINFO",
-    "IDEF",
-    "ROLL",
-    "MAX",
-    "MIN",
-    "ScanTYPE",
-    "InstCTRL",
-    "INS_$8F",
+    "6 FlipPT",
+    "8 FlipRgON",
+    "9 FlipRgOFF",
+    "7 INS_$83",
+    "7 INS_$84",
+    "8 ScanCTRL",
+    "9 SDPvTL[0]",
+    "9 SDPvTL[1]",
+    "7 GetINFO",
+    "4 IDEF",
+    "4 ROLL",
+    "3 MAX",
+    "3 MIN",
+    "8 ScanTYPE",
+    "8 InstCTRL",
+    "7 INS_$8F",
 
-    "INS_$90",
-    "INS_$91",
-    "INS_$92",
-    "INS_$93",
-    "INS_$94",
-    "INS_$95",
-    "INS_$96",
-    "INS_$97",
-    "INS_$98",
-    "INS_$99",
-    "INS_$9A",
-    "INS_$9B",
-    "INS_$9C",
-    "INS_$9D",
-    "INS_$9E",
-    "INS_$9F",
+    "7 INS_$90",
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    "6 GETVAR",
+    "7 GETDATA",
+#else
+    "7 INS_$91",
+    "7 INS_$92",
+#endif
+    "7 INS_$93",
+    "7 INS_$94",
+    "7 INS_$95",
+    "7 INS_$96",
+    "7 INS_$97",
+    "7 INS_$98",
+    "7 INS_$99",
+    "7 INS_$9A",
+    "7 INS_$9B",
+    "7 INS_$9C",
+    "7 INS_$9D",
+    "7 INS_$9E",
+    "7 INS_$9F",
 
-    "INS_$A0",
-    "INS_$A1",
-    "INS_$A2",
-    "INS_$A3",
-    "INS_$A4",
-    "INS_$A5",
-    "INS_$A6",
-    "INS_$A7",
-    "INS_$A8",
-    "INS_$A9",
-    "INS_$AA",
-    "INS_$AB",
-    "INS_$AC",
-    "INS_$AD",
-    "INS_$AE",
-    "INS_$AF",
+    "7 INS_$A0",
+    "7 INS_$A1",
+    "7 INS_$A2",
+    "7 INS_$A3",
+    "7 INS_$A4",
+    "7 INS_$A5",
+    "7 INS_$A6",
+    "7 INS_$A7",
+    "7 INS_$A8",
+    "7 INS_$A9",
+    "7 INS_$AA",
+    "7 INS_$AB",
+    "7 INS_$AC",
+    "7 INS_$AD",
+    "7 INS_$AE",
+    "7 INS_$AF",
 
-    "PushB[0]",
-    "PushB[1]",
-    "PushB[2]",
-    "PushB[3]",
-    "PushB[4]",
-    "PushB[5]",
-    "PushB[6]",
-    "PushB[7]",
-    "PushW[0]",
-    "PushW[1]",
-    "PushW[2]",
-    "PushW[3]",
-    "PushW[4]",
-    "PushW[5]",
-    "PushW[6]",
-    "PushW[7]",
+    "8 PushB[0]",
+    "8 PushB[1]",
+    "8 PushB[2]",
+    "8 PushB[3]",
+    "8 PushB[4]",
+    "8 PushB[5]",
+    "8 PushB[6]",
+    "8 PushB[7]",
+    "8 PushW[0]",
+    "8 PushW[1]",
+    "8 PushW[2]",
+    "8 PushW[3]",
+    "8 PushW[4]",
+    "8 PushW[5]",
+    "8 PushW[6]",
+    "8 PushW[7]",
 
-    "MDRP[00]",
-    "MDRP[01]",
-    "MDRP[02]",
-    "MDRP[03]",
-    "MDRP[04]",
-    "MDRP[05]",
-    "MDRP[06]",
-    "MDRP[07]",
-    "MDRP[08]",
-    "MDRP[09]",
-    "MDRP[10]",
-    "MDRP[11]",
-    "MDRP[12]",
-    "MDRP[13]",
-    "MDRP[14]",
-    "MDRP[15]",
+    "8 MDRP[00]",
+    "8 MDRP[01]",
+    "8 MDRP[02]",
+    "8 MDRP[03]",
+    "8 MDRP[04]",
+    "8 MDRP[05]",
+    "8 MDRP[06]",
+    "8 MDRP[07]",
+    "8 MDRP[08]",
+    "8 MDRP[09]",
+    "8 MDRP[10]",
+    "8 MDRP[11]",
+    "8 MDRP[12]",
+    "8 MDRP[13]",
+    "8 MDRP[14]",
+    "8 MDRP[15]",
 
-    "MDRP[16]",
-    "MDRP[17]",
-    "MDRP[18]",
-    "MDRP[19]",
-    "MDRP[20]",
-    "MDRP[21]",
-    "MDRP[22]",
-    "MDRP[23]",
-    "MDRP[24]",
-    "MDRP[25]",
-    "MDRP[26]",
-    "MDRP[27]",
-    "MDRP[28]",
-    "MDRP[29]",
-    "MDRP[30]",
-    "MDRP[31]",
+    "8 MDRP[16]",
+    "8 MDRP[17]",
+    "8 MDRP[18]",
+    "8 MDRP[19]",
+    "8 MDRP[20]",
+    "8 MDRP[21]",
+    "8 MDRP[22]",
+    "8 MDRP[23]",
+    "8 MDRP[24]",
+    "8 MDRP[25]",
+    "8 MDRP[26]",
+    "8 MDRP[27]",
+    "8 MDRP[28]",
+    "8 MDRP[29]",
+    "8 MDRP[30]",
+    "8 MDRP[31]",
 
-    "MIRP[00]",
-    "MIRP[01]",
-    "MIRP[02]",
-    "MIRP[03]",
-    "MIRP[04]",
-    "MIRP[05]",
-    "MIRP[06]",
-    "MIRP[07]",
-    "MIRP[08]",
-    "MIRP[09]",
-    "MIRP[10]",
-    "MIRP[11]",
-    "MIRP[12]",
-    "MIRP[13]",
-    "MIRP[14]",
-    "MIRP[15]",
+    "8 MIRP[00]",
+    "8 MIRP[01]",
+    "8 MIRP[02]",
+    "8 MIRP[03]",
+    "8 MIRP[04]",
+    "8 MIRP[05]",
+    "8 MIRP[06]",
+    "8 MIRP[07]",
+    "8 MIRP[08]",
+    "8 MIRP[09]",
+    "8 MIRP[10]",
+    "8 MIRP[11]",
+    "8 MIRP[12]",
+    "8 MIRP[13]",
+    "8 MIRP[14]",
+    "8 MIRP[15]",
 
-    "MIRP[16]",
-    "MIRP[17]",
-    "MIRP[18]",
-    "MIRP[19]",
-    "MIRP[20]",
-    "MIRP[21]",
-    "MIRP[22]",
-    "MIRP[23]",
-    "MIRP[24]",
-    "MIRP[25]",
-    "MIRP[26]",
-    "MIRP[27]",
-    "MIRP[28]",
-    "MIRP[29]",
-    "MIRP[30]",
-    "MIRP[31]"
+    "8 MIRP[16]",
+    "8 MIRP[17]",
+    "8 MIRP[18]",
+    "8 MIRP[19]",
+    "8 MIRP[20]",
+    "8 MIRP[21]",
+    "8 MIRP[22]",
+    "8 MIRP[23]",
+    "8 MIRP[24]",
+    "8 MIRP[25]",
+    "8 MIRP[26]",
+    "8 MIRP[27]",
+    "8 MIRP[28]",
+    "8 MIRP[29]",
+    "8 MIRP[30]",
+    "8 MIRP[31]"
   };
 
 #endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1446,7 +1235,7 @@
   TT_MulFix14_arm( FT_Int32  a,
                    FT_Int    b )
   {
-    register FT_Int32  t, t2;
+    FT_Int32  t, t2;
 
 
 #if defined( __CC_ARM ) || defined( __ARMCC__ )
@@ -1668,48 +1457,43 @@
   /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
   /*                                                                       */
   static FT_Long
-  Current_Ratio( EXEC_OP )
+  Current_Ratio( TT_ExecContext  exc )
   {
-    if ( !CUR.tt_metrics.ratio )
+    if ( !exc->tt_metrics.ratio )
     {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-      if ( CUR.face->unpatented_hinting )
-      {
-        if ( CUR.GS.both_x_axis )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
-        else
-          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
-      }
+      if ( exc->GS.projVector.y == 0 )
+        exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
+
+      else if ( exc->GS.projVector.x == 0 )
+        exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
+
       else
-#endif
       {
-        if ( CUR.GS.projVector.y == 0 )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
-
-        else if ( CUR.GS.projVector.x == 0 )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
-
-        else
-        {
-          FT_F26Dot6  x, y;
+        FT_F26Dot6  x, y;
 
 
-          x = TT_MulFix14( CUR.tt_metrics.x_ratio,
-                           CUR.GS.projVector.x );
-          y = TT_MulFix14( CUR.tt_metrics.y_ratio,
-                           CUR.GS.projVector.y );
-          CUR.tt_metrics.ratio = FT_Hypot( x, y );
-        }
+        x = TT_MulFix14( exc->tt_metrics.x_ratio,
+                         exc->GS.projVector.x );
+        y = TT_MulFix14( exc->tt_metrics.y_ratio,
+                         exc->GS.projVector.y );
+        exc->tt_metrics.ratio = FT_Hypot( x, y );
       }
     }
-    return CUR.tt_metrics.ratio;
+    return exc->tt_metrics.ratio;
   }
 
 
-  static FT_Long
-  Current_Ppem( EXEC_OP )
+  FT_CALLBACK_DEF( FT_Long )
+  Current_Ppem( TT_ExecContext  exc )
   {
-    return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+    return exc->tt_metrics.ppem;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Long )
+  Current_Ppem_Stretched( TT_ExecContext  exc )
+  {
+    return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) );
   }
 
 
@@ -1721,48 +1505,54 @@
 
 
   FT_CALLBACK_DEF( FT_F26Dot6 )
-  Read_CVT( EXEC_OP_ FT_ULong  idx )
+  Read_CVT( TT_ExecContext  exc,
+            FT_ULong        idx )
   {
-    return CUR.cvt[idx];
+    return exc->cvt[idx];
   }
 
 
   FT_CALLBACK_DEF( FT_F26Dot6 )
-  Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
+  Read_CVT_Stretched( TT_ExecContext  exc,
+                      FT_ULong        idx )
   {
-    return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
+    return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) );
   }
 
 
   FT_CALLBACK_DEF( void )
-  Write_CVT( EXEC_OP_ FT_ULong    idx,
-                      FT_F26Dot6  value )
+  Write_CVT( TT_ExecContext  exc,
+             FT_ULong        idx,
+             FT_F26Dot6      value )
   {
-    CUR.cvt[idx] = value;
+    exc->cvt[idx] = value;
   }
 
 
   FT_CALLBACK_DEF( void )
-  Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
-                                FT_F26Dot6  value )
+  Write_CVT_Stretched( TT_ExecContext  exc,
+                       FT_ULong        idx,
+                       FT_F26Dot6      value )
   {
-    CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
+    exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
   }
 
 
   FT_CALLBACK_DEF( void )
-  Move_CVT( EXEC_OP_ FT_ULong    idx,
-                     FT_F26Dot6  value )
+  Move_CVT( TT_ExecContext  exc,
+            FT_ULong        idx,
+            FT_F26Dot6      value )
   {
-    CUR.cvt[idx] += value;
+    exc->cvt[idx] += value;
   }
 
 
   FT_CALLBACK_DEF( void )
-  Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
-                               FT_F26Dot6  value )
+  Move_CVT_Stretched( TT_ExecContext  exc,
+                      FT_ULong        idx,
+                      FT_F26Dot6      value )
   {
-    CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
+    exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) );
   }
 
 
@@ -1782,12 +1572,12 @@
   /*    This one could become a macro.                                     */
   /*                                                                       */
   static FT_Short
-  GetShortIns( EXEC_OP )
+  GetShortIns( TT_ExecContext  exc )
   {
-    /* Reading a byte stream so there is no endianess (DaveP) */
-    CUR.IP += 2;
-    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
-                         CUR.code[CUR.IP - 1]      );
+    /* Reading a byte stream so there is no endianness (DaveP) */
+    exc->IP += 2;
+    return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) +
+                         exc->code[exc->IP - 1]      );
   }
 
 
@@ -1808,23 +1598,24 @@
   /*    SUCCESS or FAILURE.                                                */
   /*                                                                       */
   static FT_Bool
-  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
-                               FT_ULong  aIP )
+  Ins_Goto_CodeRange( TT_ExecContext  exc,
+                      FT_Int          aRange,
+                      FT_Long         aIP )
   {
     TT_CodeRange*  range;
 
 
     if ( aRange < 1 || aRange > 3 )
     {
-      CUR.error = FT_THROW( Bad_Argument );
+      exc->error = FT_THROW( Bad_Argument );
       return FAILURE;
     }
 
-    range = &CUR.codeRangeTable[aRange - 1];
+    range = &exc->codeRangeTable[aRange - 1];
 
     if ( range->base == NULL )     /* invalid coderange */
     {
-      CUR.error = FT_THROW( Invalid_CodeRange );
+      exc->error = FT_THROW( Invalid_CodeRange );
       return FAILURE;
     }
 
@@ -1834,14 +1625,14 @@
 
     if ( aIP > range->size )
     {
-      CUR.error = FT_THROW( Code_Overflow );
+      exc->error = FT_THROW( Code_Overflow );
       return FAILURE;
     }
 
-    CUR.code     = range->base;
-    CUR.codeSize = range->size;
-    CUR.IP       = aIP;
-    CUR.curRange = aRange;
+    exc->code     = range->base;
+    exc->codeSize = range->size;
+    exc->IP       = aIP;
+    exc->curRange = aRange;
 
     return SUCCESS;
   }
@@ -1864,37 +1655,57 @@
   /* <InOut>                                                               */
   /*    zone     :: The affected glyph zone.                               */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*    `Touches' the point.                                               */
+  /*                                                                       */
   static void
-  Direct_Move( EXEC_OP_ TT_GlyphZone  zone,
-                        FT_UShort     point,
-                        FT_F26Dot6    distance )
+  Direct_Move( TT_ExecContext  exc,
+               TT_GlyphZone    zone,
+               FT_UShort       point,
+               FT_F26Dot6      distance )
   {
     FT_F26Dot6  v;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    v = CUR.GS.freeVector.x;
+    v = exc->GS.freeVector.x;
 
     if ( v != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( !SUBPIXEL_HINTING                                     ||
-           ( !CUR.ignore_x_mode                                ||
-             ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY                            &&
+           ( !exc->ignore_x_mode                                ||
+             ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      /* Exception to the post-IUP curfew: Allow the x component of */
+      /* diagonal moves, but only post-IUP.  DejaVu tries to adjust */
+      /* diagonal stems like on `Z' and `z' post-IUP.               */
+      if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      else
+#endif
+
+      if ( NO_SUBPIXEL_HINTING )
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
 
-    v = CUR.GS.freeVector.y;
+    v = exc->GS.freeVector.y;
 
     if ( v != 0 )
     {
-      zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+#endif
+        zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -1919,26 +1730,23 @@
   /*    zone     :: The affected glyph zone.                               */
   /*                                                                       */
   static void
-  Direct_Move_Orig( EXEC_OP_ TT_GlyphZone  zone,
-                             FT_UShort     point,
-                             FT_F26Dot6    distance )
+  Direct_Move_Orig( TT_ExecContext  exc,
+                    TT_GlyphZone    zone,
+                    FT_UShort       point,
+                    FT_F26Dot6      distance )
   {
     FT_F26Dot6  v;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    v = CUR.GS.freeVector.x;
+    v = exc->GS.freeVector.x;
 
     if ( v != 0 )
-      zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
+      zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
 
-    v = CUR.GS.freeVector.y;
+    v = exc->GS.freeVector.y;
 
     if ( v != 0 )
-      zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
+      zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
   }
 
 
@@ -1948,21 +1756,30 @@
   /*                                                                       */
   /*   The following versions are used whenever both vectors are both      */
   /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+  /*   See `ttinterp.h' for details on backwards compatibility mode.       */
   /*                                                                       */
   /*************************************************************************/
 
 
   static void
-  Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,
-                          FT_UShort     point,
-                          FT_F26Dot6    distance )
+  Direct_Move_X( TT_ExecContext  exc,
+                 TT_GlyphZone    zone,
+                 FT_UShort       point,
+                 FT_F26Dot6      distance )
   {
-    FT_UNUSED_EXEC;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
+      zone->cur[point].x += distance;
+    else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( !SUBPIXEL_HINTING  ||
-         !CUR.ignore_x_mode )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
+      zone->cur[point].x += distance;
+    else
+#endif
+
+    if ( NO_SUBPIXEL_HINTING )
       zone->cur[point].x += distance;
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
@@ -1970,14 +1787,21 @@
 
 
   static void
-  Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,
-                          FT_UShort     point,
-                          FT_F26Dot6    distance )
+  Direct_Move_Y( TT_ExecContext  exc,
+                 TT_GlyphZone    zone,
+                 FT_UShort       point,
+                 FT_F26Dot6      distance )
   {
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
-    zone->cur[point].y += distance;
-    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( !( SUBPIXEL_HINTING_MINIMAL             &&
+            exc->backwards_compatibility         &&
+            exc->iupx_called && exc->iupy_called ) )
+#endif
+      zone->cur[point].y += distance;
+
+    zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   }
 
 
@@ -1992,22 +1816,24 @@
 
 
   static void
-  Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone  zone,
-                               FT_UShort     point,
-                               FT_F26Dot6    distance )
+  Direct_Move_Orig_X( TT_ExecContext  exc,
+                      TT_GlyphZone    zone,
+                      FT_UShort       point,
+                      FT_F26Dot6      distance )
   {
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
     zone->org[point].x += distance;
   }
 
 
   static void
-  Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone  zone,
-                               FT_UShort     point,
-                               FT_F26Dot6    distance )
+  Direct_Move_Orig_Y( TT_ExecContext  exc,
+                      TT_GlyphZone    zone,
+                      FT_UShort       point,
+                      FT_F26Dot6      distance )
   {
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
     zone->org[point].y += distance;
   }
@@ -2036,18 +1862,19 @@
   /*    before rounding.                                                   */
   /*                                                                       */
   static FT_F26Dot6
-  Round_None( EXEC_OP_ FT_F26Dot6  distance,
-                       FT_F26Dot6  compensation )
+  Round_None( TT_ExecContext  exc,
+              FT_F26Dot6      distance,
+              FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
       val = distance + compensation;
-      if ( distance && val < 0 )
+      if ( val < 0 )
         val = 0;
     }
     else
@@ -2077,20 +1904,19 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   static FT_F26Dot6
-  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                          FT_F26Dot6  compensation )
+  Round_To_Grid( TT_ExecContext  exc,
+                 FT_F26Dot6      distance,
+                 FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
-      val = distance + compensation + 32;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
+      val = FT_PIX_ROUND( distance + compensation );
+      if ( val < 0 )
         val = 0;
     }
     else
@@ -2100,7 +1926,7 @@
         val = 0;
     }
 
-    return  val;
+    return val;
   }
 
 
@@ -2121,25 +1947,26 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   static FT_F26Dot6
-  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                               FT_F26Dot6  compensation )
+  Round_To_Half_Grid( TT_ExecContext  exc,
+                      FT_F26Dot6      distance,
+                      FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
       val = FT_PIX_FLOOR( distance + compensation ) + 32;
-      if ( distance && val < 0 )
-        val = 0;
+      if ( val < 0 )
+        val = 32;
     }
     else
     {
       val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
       if ( val > 0 )
-        val = 0;
+        val = -32;
     }
 
     return val;
@@ -2163,25 +1990,24 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   static FT_F26Dot6
-  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                               FT_F26Dot6  compensation )
+  Round_Down_To_Grid( TT_ExecContext  exc,
+                      FT_F26Dot6      distance,
+                      FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
-      val = distance + compensation;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
+      val = FT_PIX_FLOOR( distance + compensation );
+      if ( val < 0 )
         val = 0;
     }
     else
     {
-      val = -( ( compensation - distance ) & -64 );
+      val = -FT_PIX_FLOOR( compensation - distance );
       if ( val > 0 )
         val = 0;
     }
@@ -2207,20 +2033,19 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   static FT_F26Dot6
-  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                             FT_F26Dot6  compensation )
+  Round_Up_To_Grid( TT_ExecContext  exc,
+                    FT_F26Dot6      distance,
+                    FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
-      val = distance + compensation + 63;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
+      val = FT_PIX_CEIL( distance + compensation );
+      if ( val < 0 )
         val = 0;
     }
     else
@@ -2251,20 +2076,19 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   static FT_F26Dot6
-  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                                 FT_F26Dot6  compensation )
+  Round_To_Double_Grid( TT_ExecContext  exc,
+                        FT_F26Dot6      distance,
+                        FT_F26Dot6      compensation )
   {
-    FT_F26Dot6 val;
+    FT_F26Dot6  val;
 
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
     {
-      val = distance + compensation + 16;
-      if ( distance && val > 0 )
-        val &= ~31;
-      else
+      val = FT_PAD_ROUND( distance + compensation, 32 );
+      if ( val < 0 )
         val = 0;
     }
     else
@@ -2295,33 +2119,34 @@
   /*    Rounded distance.                                                  */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    The TrueType specification says very few about the relationship    */
+  /*    The TrueType specification says very little about the relationship */
   /*    between rounding and engine compensation.  However, it seems from  */
   /*    the description of super round that we should add the compensation */
   /*    before rounding.                                                   */
   /*                                                                       */
   static FT_F26Dot6
-  Round_Super( EXEC_OP_ FT_F26Dot6  distance,
-                        FT_F26Dot6  compensation )
+  Round_Super( TT_ExecContext  exc,
+               FT_F26Dot6      distance,
+               FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
 
     if ( distance >= 0 )
     {
-      val = ( distance - CUR.phase + CUR.threshold + compensation ) &
-              -CUR.period;
-      if ( distance && val < 0 )
-        val = 0;
-      val += CUR.phase;
+      val = ( distance - exc->phase + exc->threshold + compensation ) &
+              -exc->period;
+      val += exc->phase;
+      if ( val < 0 )
+        val = exc->phase;
     }
     else
     {
-      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
-               -CUR.period );
+      val = -( ( exc->threshold - exc->phase - distance + compensation ) &
+               -exc->period );
+      val -= exc->phase;
       if ( val > 0 )
-        val = 0;
-      val -= CUR.phase;
+        val = -exc->phase;
     }
 
     return val;
@@ -2349,27 +2174,28 @@
   /*    greater precision.                                                 */
   /*                                                                       */
   static FT_F26Dot6
-  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
-                           FT_F26Dot6  compensation )
+  Round_Super_45( TT_ExecContext  exc,
+                  FT_F26Dot6      distance,
+                  FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
 
 
     if ( distance >= 0 )
     {
-      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
-                CUR.period ) * CUR.period;
-      if ( distance && val < 0 )
-        val = 0;
-      val += CUR.phase;
+      val = ( ( distance - exc->phase + exc->threshold + compensation ) /
+                exc->period ) * exc->period;
+      val += exc->phase;
+      if ( val < 0 )
+        val = exc->phase;
     }
     else
     {
-      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
-                   CUR.period ) * CUR.period );
+      val = -( ( ( exc->threshold - exc->phase - distance + compensation ) /
+                   exc->period ) * exc->period );
+      val -= exc->phase;
       if ( val > 0 )
-        val = 0;
-      val -= CUR.phase;
+        val = -exc->phase;
     }
 
     return val;
@@ -2388,40 +2214,41 @@
   /*    round_mode :: The rounding mode to be used.                        */
   /*                                                                       */
   static void
-  Compute_Round( EXEC_OP_ FT_Byte  round_mode )
+  Compute_Round( TT_ExecContext  exc,
+                 FT_Byte         round_mode )
   {
     switch ( round_mode )
     {
     case TT_Round_Off:
-      CUR.func_round = (TT_Round_Func)Round_None;
+      exc->func_round = (TT_Round_Func)Round_None;
       break;
 
     case TT_Round_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Grid;
+      exc->func_round = (TT_Round_Func)Round_To_Grid;
       break;
 
     case TT_Round_Up_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+      exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
       break;
 
     case TT_Round_Down_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+      exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
       break;
 
     case TT_Round_To_Half_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+      exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
       break;
 
     case TT_Round_To_Double_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+      exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
       break;
 
     case TT_Round_Super:
-      CUR.func_round = (TT_Round_Func)Round_Super;
+      exc->func_round = (TT_Round_Func)Round_Super;
       break;
 
     case TT_Round_Super_45:
-      CUR.func_round = (TT_Round_Func)Round_Super_45;
+      exc->func_round = (TT_Round_Func)Round_Super_45;
       break;
     }
   }
@@ -2441,57 +2268,58 @@
   /*    selector   :: The SROUND opcode.                                   */
   /*                                                                       */
   static void
-  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
-                          FT_Long     selector )
+  SetSuperRound( TT_ExecContext  exc,
+                 FT_F2Dot14      GridPeriod,
+                 FT_Long         selector )
   {
     switch ( (FT_Int)( selector & 0xC0 ) )
     {
       case 0:
-        CUR.period = GridPeriod / 2;
+        exc->period = GridPeriod / 2;
         break;
 
       case 0x40:
-        CUR.period = GridPeriod;
+        exc->period = GridPeriod;
         break;
 
       case 0x80:
-        CUR.period = GridPeriod * 2;
+        exc->period = GridPeriod * 2;
         break;
 
       /* This opcode is reserved, but... */
-
       case 0xC0:
-        CUR.period = GridPeriod;
+        exc->period = GridPeriod;
         break;
     }
 
     switch ( (FT_Int)( selector & 0x30 ) )
     {
     case 0:
-      CUR.phase = 0;
+      exc->phase = 0;
       break;
 
     case 0x10:
-      CUR.phase = CUR.period / 4;
+      exc->phase = exc->period / 4;
       break;
 
     case 0x20:
-      CUR.phase = CUR.period / 2;
+      exc->phase = exc->period / 2;
       break;
 
     case 0x30:
-      CUR.phase = CUR.period * 3 / 4;
+      exc->phase = exc->period * 3 / 4;
       break;
     }
 
     if ( ( selector & 0x0F ) == 0 )
-      CUR.threshold = CUR.period - 1;
+      exc->threshold = exc->period - 1;
     else
-      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+      exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8;
 
-    CUR.period    /= 256;
-    CUR.phase     /= 256;
-    CUR.threshold /= 256;
+    /* convert to F26Dot6 format */
+    exc->period    >>= 8;
+    exc->phase     >>= 8;
+    exc->threshold >>= 8;
   }
 
 
@@ -2512,16 +2340,13 @@
   /*    The distance in F26dot6 format.                                    */
   /*                                                                       */
   static FT_F26Dot6
-  Project( EXEC_OP_ FT_Pos  dx,
-                    FT_Pos  dy )
+  Project( TT_ExecContext  exc,
+           FT_Pos          dx,
+           FT_Pos          dy )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
-                        CUR.GS.projVector.x,
-                        CUR.GS.projVector.y );
+    return TT_DotFix14( dx, dy,
+                        exc->GS.projVector.x,
+                        exc->GS.projVector.y );
   }
 
 
@@ -2542,12 +2367,13 @@
   /*    The distance in F26dot6 format.                                    */
   /*                                                                       */
   static FT_F26Dot6
-  Dual_Project( EXEC_OP_ FT_Pos  dx,
-                         FT_Pos  dy )
+  Dual_Project( TT_ExecContext  exc,
+                FT_Pos          dx,
+                FT_Pos          dy )
   {
-    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
-                        CUR.GS.dualVector.x,
-                        CUR.GS.dualVector.y );
+    return TT_DotFix14( dx, dy,
+                        exc->GS.dualVector.x,
+                        exc->GS.dualVector.y );
   }
 
 
@@ -2568,10 +2394,11 @@
   /*    The distance in F26dot6 format.                                    */
   /*                                                                       */
   static FT_F26Dot6
-  Project_x( EXEC_OP_ FT_Pos  dx,
-                      FT_Pos  dy )
+  Project_x( TT_ExecContext  exc,
+             FT_Pos          dx,
+             FT_Pos          dy )
   {
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
     FT_UNUSED( dy );
 
     return dx;
@@ -2595,10 +2422,11 @@
   /*    The distance in F26dot6 format.                                    */
   /*                                                                       */
   static FT_F26Dot6
-  Project_y( EXEC_OP_ FT_Pos  dx,
-                      FT_Pos  dy )
+  Project_y( TT_ExecContext  exc,
+             FT_Pos          dx,
+             FT_Pos          dy )
   {
-    FT_UNUSED_EXEC;
+    FT_UNUSED( exc );
     FT_UNUSED( dx );
 
     return dy;
@@ -2615,101 +2443,56 @@
   /*    to the current graphics state.                                     */
   /*                                                                       */
   static void
-  Compute_Funcs( EXEC_OP )
+  Compute_Funcs( TT_ExecContext  exc )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
+    if ( exc->GS.freeVector.x == 0x4000 )
+      exc->F_dot_P = exc->GS.projVector.x;
+    else if ( exc->GS.freeVector.y == 0x4000 )
+      exc->F_dot_P = exc->GS.projVector.y;
+    else
+      exc->F_dot_P =
+        ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
+          (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14;
+
+    if ( exc->GS.projVector.x == 0x4000 )
+      exc->func_project = (TT_Project_Func)Project_x;
+    else if ( exc->GS.projVector.y == 0x4000 )
+      exc->func_project = (TT_Project_Func)Project_y;
+    else
+      exc->func_project = (TT_Project_Func)Project;
+
+    if ( exc->GS.dualVector.x == 0x4000 )
+      exc->func_dualproj = (TT_Project_Func)Project_x;
+    else if ( exc->GS.dualVector.y == 0x4000 )
+      exc->func_dualproj = (TT_Project_Func)Project_y;
+    else
+      exc->func_dualproj = (TT_Project_Func)Dual_Project;
+
+    exc->func_move      = (TT_Move_Func)Direct_Move;
+    exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig;
+
+    if ( exc->F_dot_P == 0x4000L )
     {
-      /* If both vectors point rightwards along the x axis, set             */
-      /* `both-x-axis' true, otherwise set it false.  The x values only     */
-      /* need be tested because the vector has been normalised to a unit    */
-      /* vector of length 0x4000 = unity.                                   */
-      CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
-                                      CUR.GS.freeVector.x == 0x4000 );
-
-      /* Throw away projection and freedom vector information */
-      /* because the patents don't allow them to be stored.   */
-      /* The relevant US Patents are 5155805 and 5325479.     */
-      CUR.GS.projVector.x = 0;
-      CUR.GS.projVector.y = 0;
-      CUR.GS.freeVector.x = 0;
-      CUR.GS.freeVector.y = 0;
-
-      if ( CUR.GS.both_x_axis )
+      if ( exc->GS.freeVector.x == 0x4000 )
       {
-        CUR.func_project   = Project_x;
-        CUR.func_move      = Direct_Move_X;
-        CUR.func_move_orig = Direct_Move_Orig_X;
+        exc->func_move      = (TT_Move_Func)Direct_Move_X;
+        exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
       }
-      else
+      else if ( exc->GS.freeVector.y == 0x4000 )
       {
-        CUR.func_project   = Project_y;
-        CUR.func_move      = Direct_Move_Y;
-        CUR.func_move_orig = Direct_Move_Orig_Y;
-      }
-
-      if ( CUR.GS.dualVector.x == 0x4000 )
-        CUR.func_dualproj = Project_x;
-      else if ( CUR.GS.dualVector.y == 0x4000 )
-        CUR.func_dualproj = Project_y;
-      else
-        CUR.func_dualproj = Dual_Project;
-
-      /* Force recalculation of cached aspect ratio */
-      CUR.tt_metrics.ratio = 0;
-
-      return;
-    }
-#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
-
-    if ( CUR.GS.freeVector.x == 0x4000 )
-      CUR.F_dot_P = CUR.GS.projVector.x;
-    else if ( CUR.GS.freeVector.y == 0x4000 )
-      CUR.F_dot_P = CUR.GS.projVector.y;
-    else
-      CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
-                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
-                    14;
-
-    if ( CUR.GS.projVector.x == 0x4000 )
-      CUR.func_project = (TT_Project_Func)Project_x;
-    else if ( CUR.GS.projVector.y == 0x4000 )
-      CUR.func_project = (TT_Project_Func)Project_y;
-    else
-      CUR.func_project = (TT_Project_Func)Project;
-
-    if ( CUR.GS.dualVector.x == 0x4000 )
-      CUR.func_dualproj = (TT_Project_Func)Project_x;
-    else if ( CUR.GS.dualVector.y == 0x4000 )
-      CUR.func_dualproj = (TT_Project_Func)Project_y;
-    else
-      CUR.func_dualproj = (TT_Project_Func)Dual_Project;
-
-    CUR.func_move      = (TT_Move_Func)Direct_Move;
-    CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
-
-    if ( CUR.F_dot_P == 0x4000L )
-    {
-      if ( CUR.GS.freeVector.x == 0x4000 )
-      {
-        CUR.func_move      = (TT_Move_Func)Direct_Move_X;
-        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
-      }
-      else if ( CUR.GS.freeVector.y == 0x4000 )
-      {
-        CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
-        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
+        exc->func_move      = (TT_Move_Func)Direct_Move_Y;
+        exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
       }
     }
 
     /* at small sizes, F_dot_P can become too small, resulting   */
     /* in overflows and `spikes' in a number of glyphs like `w'. */
 
-    if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
-      CUR.F_dot_P = 0x4000L;
+    if ( FT_ABS( exc->F_dot_P ) < 0x400L )
+      exc->F_dot_P = 0x4000L;
 
     /* Disable cached aspect ratio */
-    CUR.tt_metrics.ratio = 0;
+    exc->tt_metrics.ratio = 0;
   }
 
 
@@ -2732,36 +2515,31 @@
   /*    Returns FAILURE if a vector parameter is zero.                     */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
+  /*    In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and  */
   /*    R is undefined.                                                    */
   /*                                                                       */
   static FT_Bool
-  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
-                      FT_F26Dot6      Vy,
-                      FT_UnitVector*  R )
+  Normalize( FT_F26Dot6      Vx,
+             FT_F26Dot6      Vy,
+             FT_UnitVector*  R )
   {
-    FT_F26Dot6  W;
-
-    FT_UNUSED_EXEC;
+    FT_Vector V;
 
 
-    if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
+    if ( Vx == 0 && Vy == 0 )
     {
-      if ( Vx == 0 && Vy == 0 )
-      {
-        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
-        /*      to normalize the vector (0,0).  Return immediately. */
-        return SUCCESS;
-      }
-
-      Vx *= 0x4000;
-      Vy *= 0x4000;
+      /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
+      /*      to normalize the vector (0,0).  Return immediately. */
+      return SUCCESS;
     }
 
-    W = FT_Hypot( Vx, Vy );
+    V.x = Vx;
+    V.y = Vy;
 
-    R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
-    R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
+    FT_Vector_NormLen( &V );
+
+    R->x = (FT_F2Dot14)( V.x / 4 );
+    R->y = (FT_F2Dot14)( V.y / 4 );
 
     return SUCCESS;
   }
@@ -2774,1062 +2552,12 @@
   /*************************************************************************/
 
 
-  static FT_Bool
-  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
-                      FT_UShort       aIdx2,
-                      FT_Int          aOpc,
-                      FT_UnitVector*  Vec )
-  {
-    FT_Long     A, B, C;
-    FT_Vector*  p1;
-    FT_Vector*  p2;
-
-
-    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
-         BOUNDS( aIdx2, CUR.zp1.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
-      return FAILURE;
-    }
-
-    p1 = CUR.zp1.cur + aIdx2;
-    p2 = CUR.zp2.cur + aIdx1;
-
-    A = p1->x - p2->x;
-    B = p1->y - p2->y;
-
-    /* If p1 == p2, SPVTL and SFVTL behave the same as */
-    /* SPVTCA[X] and SFVTCA[X], respectively.          */
-    /*                                                 */
-    /* Confirmed by Greg Hitchcock.                    */
-
-    if ( A == 0 && B == 0 )
-    {
-      A    = 0x4000;
-      aOpc = 0;
-    }
-
-    if ( ( aOpc & 1 ) != 0 )
-    {
-      C =  B;   /* counter clockwise rotation */
-      B =  A;
-      A = -C;
-    }
-
-    NORMalize( A, B, Vec );
-
-    return SUCCESS;
-  }
-
-
-  /* When not using the big switch statements, the interpreter uses a */
-  /* call table defined later below in this source.  Each opcode must */
-  /* thus have a corresponding function, even trivial ones.           */
-  /*                                                                  */
-  /* They are all defined there.                                      */
-
-#define DO_SVTCA                            \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.freeVector.x = A;                \
-    CUR.GS.projVector.x = A;                \
-    CUR.GS.dualVector.x = A;                \
-                                            \
-    CUR.GS.freeVector.y = B;                \
-    CUR.GS.projVector.y = B;                \
-    CUR.GS.dualVector.y = B;                \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SPVTCA                           \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.projVector.x = A;                \
-    CUR.GS.dualVector.x = A;                \
-                                            \
-    CUR.GS.projVector.y = B;                \
-    CUR.GS.dualVector.y = B;                \
-                                            \
-    GUESS_VECTOR( freeVector );             \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SFVTCA                           \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.freeVector.x = A;                \
-    CUR.GS.freeVector.y = B;                \
-                                            \
-    GUESS_VECTOR( projVector );             \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SPVTL                                      \
-    if ( INS_SxVTL( (FT_UShort)args[1],               \
-                    (FT_UShort)args[0],               \
-                    CUR.opcode,                       \
-                    &CUR.GS.projVector ) == SUCCESS ) \
-    {                                                 \
-      CUR.GS.dualVector = CUR.GS.projVector;          \
-      GUESS_VECTOR( freeVector );                     \
-      COMPUTE_Funcs();                                \
-    }
-
-
-#define DO_SFVTL                                      \
-    if ( INS_SxVTL( (FT_UShort)args[1],               \
-                    (FT_UShort)args[0],               \
-                    CUR.opcode,                       \
-                    &CUR.GS.freeVector ) == SUCCESS ) \
-    {                                                 \
-      GUESS_VECTOR( projVector );                     \
-      COMPUTE_Funcs();                                \
-    }
-
-
-#define DO_SFVTPV                          \
-    GUESS_VECTOR( projVector );            \
-    CUR.GS.freeVector = CUR.GS.projVector; \
-    COMPUTE_Funcs();
-
-
-#define DO_SPVFS                                \
-  {                                             \
-    FT_Short  S;                                \
-    FT_Long   X, Y;                             \
-                                                \
-                                                \
-    /* Only use low 16bits, then sign extend */ \
-    S = (FT_Short)args[1];                      \
-    Y = (FT_Long)S;                             \
-    S = (FT_Short)args[0];                      \
-    X = (FT_Long)S;                             \
-                                                \
-    NORMalize( X, Y, &CUR.GS.projVector );      \
-                                                \
-    CUR.GS.dualVector = CUR.GS.projVector;      \
-    GUESS_VECTOR( freeVector );                 \
-    COMPUTE_Funcs();                            \
-  }
-
-
-#define DO_SFVFS                                \
-  {                                             \
-    FT_Short  S;                                \
-    FT_Long   X, Y;                             \
-                                                \
-                                                \
-    /* Only use low 16bits, then sign extend */ \
-    S = (FT_Short)args[1];                      \
-    Y = (FT_Long)S;                             \
-    S = (FT_Short)args[0];                      \
-    X = S;                                      \
-                                                \
-    NORMalize( X, Y, &CUR.GS.freeVector );      \
-    GUESS_VECTOR( projVector );                 \
-    COMPUTE_Funcs();                            \
-  }
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GPV                                   \
-    if ( CUR.face->unpatented_hinting )          \
-    {                                            \
-      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
-      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
-    }                                            \
-    else                                         \
-    {                                            \
-      args[0] = CUR.GS.projVector.x;             \
-      args[1] = CUR.GS.projVector.y;             \
-    }
-#else
-#define DO_GPV                                   \
-    args[0] = CUR.GS.projVector.x;               \
-    args[1] = CUR.GS.projVector.y;
-#endif
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GFV                                   \
-    if ( CUR.face->unpatented_hinting )          \
-    {                                            \
-      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
-      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
-    }                                            \
-    else                                         \
-    {                                            \
-      args[0] = CUR.GS.freeVector.x;             \
-      args[1] = CUR.GS.freeVector.y;             \
-    }
-#else
-#define DO_GFV                                   \
-    args[0] = CUR.GS.freeVector.x;               \
-    args[1] = CUR.GS.freeVector.y;
-#endif
-
-
-#define DO_SRP0                      \
-    CUR.GS.rp0 = (FT_UShort)args[0];
-
-
-#define DO_SRP1                      \
-    CUR.GS.rp1 = (FT_UShort)args[0];
-
-
-#define DO_SRP2                      \
-    CUR.GS.rp2 = (FT_UShort)args[0];
-
-
-#define DO_RTHG                                         \
-    CUR.GS.round_state = TT_Round_To_Half_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
-
-
-#define DO_RTG                                     \
-    CUR.GS.round_state = TT_Round_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Grid;
-
-
-#define DO_RTDG                                           \
-    CUR.GS.round_state = TT_Round_To_Double_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
-
-
-#define DO_RUTG                                       \
-    CUR.GS.round_state = TT_Round_Up_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
-
-
-#define DO_RDTG                                         \
-    CUR.GS.round_state = TT_Round_Down_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
-
-
-#define DO_ROFF                                 \
-    CUR.GS.round_state = TT_Round_Off;          \
-    CUR.func_round = (TT_Round_Func)Round_None;
-
-
-#define DO_SROUND                                \
-    SET_SuperRound( 0x4000, args[0] );           \
-    CUR.GS.round_state = TT_Round_Super;         \
-    CUR.func_round = (TT_Round_Func)Round_Super;
-
-
-#define DO_S45ROUND                                 \
-    SET_SuperRound( 0x2D41, args[0] );              \
-    CUR.GS.round_state = TT_Round_Super_45;         \
-    CUR.func_round = (TT_Round_Func)Round_Super_45;
-
-
-#define DO_SLOOP                            \
-    if ( args[0] < 0 )                      \
-      CUR.error = FT_THROW( Bad_Argument ); \
-    else                                    \
-      CUR.GS.loop = args[0];
-
-
-#define DO_SMD                         \
-    CUR.GS.minimum_distance = args[0];
-
-
-#define DO_SCVTCI                                     \
-    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
-
-
-#define DO_SSWCI                                     \
-    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
-
-
-#define DO_SSW                                                     \
-    CUR.GS.single_width_value = FT_MulFix( args[0],                \
-                                           CUR.tt_metrics.scale );
-
-
-#define DO_FLIPON            \
-    CUR.GS.auto_flip = TRUE;
-
-
-#define DO_FLIPOFF            \
-    CUR.GS.auto_flip = FALSE;
-
-
-#define DO_SDB                             \
-    CUR.GS.delta_base = (FT_Short)args[0];
-
-
-#define DO_SDS                              \
-    CUR.GS.delta_shift = (FT_Short)args[0];
-
-
-#define DO_MD  /* nothing */
-
-
-#define DO_MPPEM              \
-    args[0] = CURRENT_Ppem();
-
-
-  /* Note: The pointSize should be irrelevant in a given font program; */
-  /*       we thus decide to return only the ppem.                     */
-#if 0
-
-#define DO_MPS                       \
-    args[0] = CUR.metrics.pointSize;
-
-#else
-
-#define DO_MPS                \
-    args[0] = CURRENT_Ppem();
-
-#endif /* 0 */
-
-
-#define DO_DUP         \
-    args[1] = args[0];
-
-
-#define DO_CLEAR     \
-    CUR.new_top = 0;
-
-
-#define DO_SWAP        \
-  {                    \
-    FT_Long  L;        \
-                       \
-                       \
-    L       = args[0]; \
-    args[0] = args[1]; \
-    args[1] = L;       \
-  }
-
-
-#define DO_DEPTH       \
-    args[0] = CUR.top;
-
-
-#define DO_CINDEX                                  \
-  {                                                \
-    FT_Long  L;                                    \
-                                                   \
-                                                   \
-    L = args[0];                                   \
-                                                   \
-    if ( L <= 0 || L > CUR.args )                  \
-    {                                              \
-      if ( CUR.pedantic_hinting )                  \
-        CUR.error = FT_THROW( Invalid_Reference ); \
-      args[0] = 0;                                 \
-    }                                              \
-    else                                           \
-      args[0] = CUR.stack[CUR.args - L];           \
-  }
-
-
-#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].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].Def->end ) )  \
-        CUR.error = FT_THROW( Bad_Argument );                      \
-      CUR.step_ins = FALSE;                                        \
-    }
-
-
-#define DO_LT                        \
-    args[0] = ( args[0] < args[1] );
-
-
-#define DO_LTEQ                       \
-    args[0] = ( args[0] <= args[1] );
-
-
-#define DO_GT                        \
-    args[0] = ( args[0] > args[1] );
-
-
-#define DO_GTEQ                       \
-    args[0] = ( args[0] >= args[1] );
-
-
-#define DO_EQ                         \
-    args[0] = ( args[0] == args[1] );
-
-
-#define DO_NEQ                        \
-    args[0] = ( args[0] != args[1] );
-
-
-#define DO_ODD                                                  \
-    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
-
-
-#define DO_EVEN                                                \
-    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
-
-
-#define DO_AND                        \
-    args[0] = ( args[0] && args[1] );
-
-
-#define DO_OR                         \
-    args[0] = ( args[0] || args[1] );
-
-
-#define DO_NOT          \
-    args[0] = !args[0];
-
-
-#define DO_ADD          \
-    args[0] += args[1];
-
-
-#define DO_SUB          \
-    args[0] -= args[1];
-
-
-#define DO_DIV                                               \
-    if ( args[1] == 0 )                                      \
-      CUR.error = FT_THROW( Divide_By_Zero );                \
-    else                                                     \
-      args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
-
-
-#define DO_MUL                                    \
-    args[0] = FT_MulDiv( args[0], args[1], 64L );
-
-
-#define DO_ABS                   \
-    args[0] = FT_ABS( args[0] );
-
-
-#define DO_NEG          \
-    args[0] = -args[0];
-
-
-#define DO_FLOOR    \
-    args[0] = FT_PIX_FLOOR( args[0] );
-
-
-#define DO_CEILING                    \
-    args[0] = FT_PIX_CEIL( args[0] );
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-
-#define DO_RS                                             \
-   {                                                      \
-     FT_ULong  I = (FT_ULong)args[0];                     \
-                                                          \
-                                                          \
-     if ( BOUNDSL( I, CUR.storeSize ) )                   \
-     {                                                    \
-       if ( CUR.pedantic_hinting )                        \
-         ARRAY_BOUND_ERROR;                               \
-       else                                               \
-         args[0] = 0;                                     \
-     }                                                    \
-     else                                                 \
-     {                                                    \
-       /* subpixel hinting - avoid Typeman Dstroke and */ \
-       /* IStroke and Vacuform rounds                  */ \
-                                                          \
-       if ( SUBPIXEL_HINTING                           && \
-            CUR.ignore_x_mode                          && \
-            ( ( I == 24                            &&     \
-                ( CUR.face->sph_found_func_flags &        \
-                  ( SPH_FDEF_SPACING_1 |                  \
-                    SPH_FDEF_SPACING_2 )         ) ) ||   \
-              ( I == 22                      &&           \
-                ( CUR.sph_in_func_flags    &              \
-                  SPH_FDEF_TYPEMAN_STROKES ) )       ||   \
-              ( I == 8                             &&     \
-                ( CUR.face->sph_found_func_flags &        \
-                  SPH_FDEF_VACUFORM_ROUND_1      ) &&     \
-                  CUR.iup_called                   ) ) )  \
-         args[0] = 0;                                     \
-       else                                               \
-         args[0] = CUR.storage[I];                        \
-     }                                                    \
-   }
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-#define DO_RS                           \
-   {                                    \
-     FT_ULong  I = (FT_ULong)args[0];   \
-                                        \
-                                        \
-     if ( BOUNDSL( I, CUR.storeSize ) ) \
-     {                                  \
-       if ( CUR.pedantic_hinting )      \
-       {                                \
-         ARRAY_BOUND_ERROR;             \
-       }                                \
-       else                             \
-         args[0] = 0;                   \
-     }                                  \
-     else                               \
-       args[0] = CUR.storage[I];        \
-   }
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-
-#define DO_WS                           \
-   {                                    \
-     FT_ULong  I = (FT_ULong)args[0];   \
-                                        \
-                                        \
-     if ( BOUNDSL( I, CUR.storeSize ) ) \
-     {                                  \
-       if ( CUR.pedantic_hinting )      \
-       {                                \
-         ARRAY_BOUND_ERROR;             \
-       }                                \
-     }                                  \
-     else                               \
-       CUR.storage[I] = args[1];        \
-   }
-
-
-#define DO_RCVT                          \
-   {                                     \
-     FT_ULong  I = (FT_ULong)args[0];    \
-                                         \
-                                         \
-     if ( BOUNDSL( I, CUR.cvtSize ) )    \
-     {                                   \
-       if ( CUR.pedantic_hinting )       \
-       {                                 \
-         ARRAY_BOUND_ERROR;              \
-       }                                 \
-       else                              \
-         args[0] = 0;                    \
-     }                                   \
-     else                                \
-       args[0] = CUR_Func_read_cvt( I ); \
-   }
-
-
-#define DO_WCVTP                         \
-   {                                     \
-     FT_ULong  I = (FT_ULong)args[0];    \
-                                         \
-                                         \
-     if ( BOUNDSL( I, CUR.cvtSize ) )    \
-     {                                   \
-       if ( CUR.pedantic_hinting )       \
-       {                                 \
-         ARRAY_BOUND_ERROR;              \
-       }                                 \
-     }                                   \
-     else                                \
-       CUR_Func_write_cvt( I, args[1] ); \
-   }
-
-
-#define DO_WCVTF                                                \
-   {                                                            \
-     FT_ULong  I = (FT_ULong)args[0];                           \
-                                                                \
-                                                                \
-     if ( BOUNDSL( I, CUR.cvtSize ) )                           \
-     {                                                          \
-       if ( CUR.pedantic_hinting )                              \
-       {                                                        \
-         ARRAY_BOUND_ERROR;                                     \
-       }                                                        \
-     }                                                          \
-     else                                                       \
-       CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \
-   }
-
-
-#define DO_DEBUG                          \
-    CUR.error = FT_THROW( Debug_OpCode );
-
-
-#define DO_ROUND                                                   \
-    args[0] = CUR_Func_round(                                      \
-                args[0],                                           \
-                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
-
-
-#define DO_NROUND                                                            \
-    args[0] = ROUND_None( args[0],                                           \
-                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
-
-
-#define DO_MAX               \
-    if ( args[1] > args[0] ) \
-      args[0] = args[1];
-
-
-#define DO_MIN               \
-    if ( args[1] < args[0] ) \
-      args[0] = args[1];
-
-
-#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
-
-#undef  ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR                        \
-    {                                            \
-      CUR.error = FT_THROW( Invalid_Reference ); \
-      return;                                    \
-    }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
-  /* Opcode range: 0x00-0x01                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SVTCA( INS_ARG )
-  {
-    DO_SVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
-  /* Opcode range: 0x02-0x03                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SPVTCA( INS_ARG )
-  {
-    DO_SPVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
-  /* Opcode range: 0x04-0x05                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SFVTCA( INS_ARG )
-  {
-    DO_SFVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVTL[a]:     Set PVector To Line                                     */
-  /* Opcode range: 0x06-0x07                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_SPVTL( INS_ARG )
-  {
-    DO_SPVTL
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTL[a]:     Set FVector To Line                                     */
-  /* Opcode range: 0x08-0x09                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_SFVTL( INS_ARG )
-  {
-    DO_SFVTL
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTPV[]:     Set FVector To PVector                                  */
-  /* Opcode range: 0x0E                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SFVTPV( INS_ARG )
-  {
-    DO_SFVTPV
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVFS[]:      Set PVector From Stack                                  */
-  /* Opcode range: 0x0A                                                    */
-  /* Stack:        f2.14 f2.14 -->                                         */
-  /*                                                                       */
-  static void
-  Ins_SPVFS( INS_ARG )
-  {
-    DO_SPVFS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVFS[]:      Set FVector From Stack                                  */
-  /* Opcode range: 0x0B                                                    */
-  /* Stack:        f2.14 f2.14 -->                                         */
-  /*                                                                       */
-  static void
-  Ins_SFVFS( INS_ARG )
-  {
-    DO_SFVFS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GPV[]:        Get Projection Vector                                   */
-  /* Opcode range: 0x0C                                                    */
-  /* Stack:        ef2.14 --> ef2.14                                       */
-  /*                                                                       */
-  static void
-  Ins_GPV( INS_ARG )
-  {
-    DO_GPV
-  }
-
-
-  /*************************************************************************/
-  /* GFV[]:        Get Freedom Vector                                      */
-  /* Opcode range: 0x0D                                                    */
-  /* Stack:        ef2.14 --> ef2.14                                       */
-  /*                                                                       */
-  static void
-  Ins_GFV( INS_ARG )
-  {
-    DO_GFV
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP0[]:       Set Reference Point 0                                   */
-  /* Opcode range: 0x10                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP0( INS_ARG )
-  {
-    DO_SRP0
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP1[]:       Set Reference Point 1                                   */
-  /* Opcode range: 0x11                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP1( INS_ARG )
-  {
-    DO_SRP1
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP2[]:       Set Reference Point 2                                   */
-  /* Opcode range: 0x12                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP2( INS_ARG )
-  {
-    DO_SRP2
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RTHG[]:       Round To Half Grid                                      */
-  /* Opcode range: 0x19                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTHG( INS_ARG )
-  {
-    DO_RTHG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RTG[]:        Round To Grid                                           */
-  /* Opcode range: 0x18                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTG( INS_ARG )
-  {
-    DO_RTG
-  }
-
-
-  /*************************************************************************/
-  /* RTDG[]:       Round To Double Grid                                    */
-  /* Opcode range: 0x3D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTDG( INS_ARG )
-  {
-    DO_RTDG
-  }
-
-
-  /*************************************************************************/
-  /* RUTG[]:       Round Up To Grid                                        */
-  /* Opcode range: 0x7C                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RUTG( INS_ARG )
-  {
-    DO_RUTG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RDTG[]:       Round Down To Grid                                      */
-  /* Opcode range: 0x7D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RDTG( INS_ARG )
-  {
-    DO_RDTG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ROFF[]:       Round OFF                                               */
-  /* Opcode range: 0x7A                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_ROFF( INS_ARG )
-  {
-    DO_ROFF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SROUND[]:     Super ROUND                                             */
-  /* Opcode range: 0x76                                                    */
-  /* Stack:        Eint8 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SROUND( INS_ARG )
-  {
-    DO_SROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
-  /* Opcode range: 0x77                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_S45ROUND( INS_ARG )
-  {
-    DO_S45ROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SLOOP[]:      Set LOOP variable                                       */
-  /* Opcode range: 0x17                                                    */
-  /* Stack:        int32? -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SLOOP( INS_ARG )
-  {
-    DO_SLOOP
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SMD[]:        Set Minimum Distance                                    */
-  /* Opcode range: 0x1A                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SMD( INS_ARG )
-  {
-    DO_SMD
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SCVTCI[]:     Set Control Value Table Cut In                          */
-  /* Opcode range: 0x1D                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SCVTCI( INS_ARG )
-  {
-    DO_SCVTCI
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SSWCI[]:      Set Single Width Cut In                                 */
-  /* Opcode range: 0x1E                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SSWCI( INS_ARG )
-  {
-    DO_SSWCI
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SSW[]:        Set Single Width                                        */
-  /* Opcode range: 0x1F                                                    */
-  /* Stack:        int32? -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SSW( INS_ARG )
-  {
-    DO_SSW
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPON[]:     Set auto-FLIP to ON                                     */
-  /* Opcode range: 0x4D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_FLIPON( INS_ARG )
-  {
-    DO_FLIPON
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
-  /* Opcode range: 0x4E                                                    */
-  /* Stack: -->                                                            */
-  /*                                                                       */
-  static void
-  Ins_FLIPOFF( INS_ARG )
-  {
-    DO_FLIPOFF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SANGW[]:      Set ANGle Weight                                        */
-  /* Opcode range: 0x7E                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SANGW( INS_ARG )
-  {
-    /* instruction not supported anymore */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SDB[]:        Set Delta Base                                          */
-  /* Opcode range: 0x5E                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SDB( INS_ARG )
-  {
-    DO_SDB
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SDS[]:        Set Delta Shift                                         */
-  /* Opcode range: 0x5F                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SDS( INS_ARG )
-  {
-    DO_SDS
-  }
+#define ARRAY_BOUND_ERROR                         \
+    do                                            \
+    {                                             \
+      exc->error = FT_THROW( Invalid_Reference ); \
+      return;                                     \
+    } while (0)
 
 
   /*************************************************************************/
@@ -3839,9 +2567,10 @@
   /* Stack:        --> Euint16                                             */
   /*                                                                       */
   static void
-  Ins_MPPEM( INS_ARG )
+  Ins_MPPEM( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    DO_MPPEM
+    args[0] = exc->func_cur_ppem( exc );
   }
 
 
@@ -3852,22 +2581,36 @@
   /* Stack:        --> Euint16                                             */
   /*                                                                       */
   static void
-  Ins_MPS( INS_ARG )
+  Ins_MPS( TT_ExecContext  exc,
+           FT_Long*        args )
   {
-    DO_MPS
+    if ( NO_SUBPIXEL_HINTING )
+    {
+      /* Microsoft's GDI bytecode interpreter always returns value 12; */
+      /* we return the current PPEM value instead.                     */
+      args[0] = exc->func_cur_ppem( exc );
+    }
+    else
+    {
+      /* A possible practical application of the MPS instruction is to   */
+      /* implement optical scaling and similar features, which should be */
+      /* based on perceptual attributes, thus independent of the         */
+      /* resolution.                                                     */
+      args[0] = exc->pointSize;
+    }
   }
 
 
   /*************************************************************************/
   /*                                                                       */
-  /* DUP[]:        DUPlicate the top stack's element                       */
+  /* DUP[]:        DUPlicate the stack's top element                       */
   /* Opcode range: 0x20                                                    */
   /* Stack:        StkElt --> StkElt StkElt                                */
   /*                                                                       */
   static void
-  Ins_DUP( INS_ARG )
+  Ins_DUP( FT_Long*  args )
   {
-    DO_DUP
+    args[1] = args[0];
   }
 
 
@@ -3878,7 +2621,7 @@
   /* Stack:        StkElt -->                                              */
   /*                                                                       */
   static void
-  Ins_POP( INS_ARG )
+  Ins_POP( void )
   {
     /* nothing to do */
   }
@@ -3891,9 +2634,9 @@
   /* Stack:        StkElt... -->                                           */
   /*                                                                       */
   static void
-  Ins_CLEAR( INS_ARG )
+  Ins_CLEAR( TT_ExecContext  exc )
   {
-    DO_CLEAR
+    exc->new_top = 0;
   }
 
 
@@ -3904,9 +2647,14 @@
   /* Stack:        2 * StkElt --> 2 * StkElt                               */
   /*                                                                       */
   static void
-  Ins_SWAP( INS_ARG )
+  Ins_SWAP( FT_Long*  args )
   {
-    DO_SWAP
+    FT_Long  L;
+
+
+    L       = args[0];
+    args[0] = args[1];
+    args[1] = L;
   }
 
 
@@ -3917,74 +2665,10 @@
   /* Stack:        --> uint32                                              */
   /*                                                                       */
   static void
-  Ins_DEPTH( INS_ARG )
+  Ins_DEPTH( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    DO_DEPTH
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* CINDEX[]:     Copy INDEXed element                                    */
-  /* Opcode range: 0x25                                                    */
-  /* Stack:        int32 --> StkElt                                        */
-  /*                                                                       */
-  static void
-  Ins_CINDEX( INS_ARG )
-  {
-    DO_CINDEX
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* EIF[]:        End IF                                                  */
-  /* Opcode range: 0x59                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_EIF( INS_ARG )
-  {
-    /* nothing to do */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JROT[]:       Jump Relative On True                                   */
-  /* Opcode range: 0x78                                                    */
-  /* Stack:        StkElt int32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_JROT( INS_ARG )
-  {
-    DO_JROT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JMPR[]:       JuMP Relative                                           */
-  /* Opcode range: 0x1C                                                    */
-  /* Stack:        int32 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_JMPR( INS_ARG )
-  {
-    DO_JMPR
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JROF[]:       Jump Relative On False                                  */
-  /* Opcode range: 0x79                                                    */
-  /* Stack:        StkElt int32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_JROF( INS_ARG )
-  {
-    DO_JROF
+    args[0] = exc->top;
   }
 
 
@@ -3995,9 +2679,9 @@
   /* Stack:        int32? int32? --> bool                                  */
   /*                                                                       */
   static void
-  Ins_LT( INS_ARG )
+  Ins_LT( FT_Long*  args )
   {
-    DO_LT
+    args[0] = ( args[0] < args[1] );
   }
 
 
@@ -4008,9 +2692,9 @@
   /* Stack:        int32? int32? --> bool                                  */
   /*                                                                       */
   static void
-  Ins_LTEQ( INS_ARG )
+  Ins_LTEQ( FT_Long*  args )
   {
-    DO_LTEQ
+    args[0] = ( args[0] <= args[1] );
   }
 
 
@@ -4021,9 +2705,9 @@
   /* Stack:        int32? int32? --> bool                                  */
   /*                                                                       */
   static void
-  Ins_GT( INS_ARG )
+  Ins_GT( FT_Long*  args )
   {
-    DO_GT
+    args[0] = ( args[0] > args[1] );
   }
 
 
@@ -4034,9 +2718,9 @@
   /* Stack:        int32? int32? --> bool                                  */
   /*                                                                       */
   static void
-  Ins_GTEQ( INS_ARG )
+  Ins_GTEQ( FT_Long*  args )
   {
-    DO_GTEQ
+    args[0] = ( args[0] >= args[1] );
   }
 
 
@@ -4047,9 +2731,9 @@
   /* Stack:        StkElt StkElt --> bool                                  */
   /*                                                                       */
   static void
-  Ins_EQ( INS_ARG )
+  Ins_EQ( FT_Long*  args )
   {
-    DO_EQ
+    args[0] = ( args[0] == args[1] );
   }
 
 
@@ -4060,9 +2744,9 @@
   /* Stack:        StkElt StkElt --> bool                                  */
   /*                                                                       */
   static void
-  Ins_NEQ( INS_ARG )
+  Ins_NEQ( FT_Long*  args )
   {
-    DO_NEQ
+    args[0] = ( args[0] != args[1] );
   }
 
 
@@ -4073,9 +2757,10 @@
   /* Stack:        f26.6 --> bool                                          */
   /*                                                                       */
   static void
-  Ins_ODD( INS_ARG )
+  Ins_ODD( TT_ExecContext  exc,
+           FT_Long*        args )
   {
-    DO_ODD
+    args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 64 );
   }
 
 
@@ -4086,9 +2771,10 @@
   /* Stack:        f26.6 --> bool                                          */
   /*                                                                       */
   static void
-  Ins_EVEN( INS_ARG )
+  Ins_EVEN( TT_ExecContext  exc,
+            FT_Long*        args )
   {
-    DO_EVEN
+    args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 0 );
   }
 
 
@@ -4099,9 +2785,9 @@
   /* Stack:        uint32 uint32 --> uint32                                */
   /*                                                                       */
   static void
-  Ins_AND( INS_ARG )
+  Ins_AND( FT_Long*  args )
   {
-    DO_AND
+    args[0] = ( args[0] && args[1] );
   }
 
 
@@ -4112,9 +2798,9 @@
   /* Stack:        uint32 uint32 --> uint32                                */
   /*                                                                       */
   static void
-  Ins_OR( INS_ARG )
+  Ins_OR( FT_Long*  args )
   {
-    DO_OR
+    args[0] = ( args[0] || args[1] );
   }
 
 
@@ -4125,9 +2811,9 @@
   /* Stack:        StkElt --> uint32                                       */
   /*                                                                       */
   static void
-  Ins_NOT( INS_ARG )
+  Ins_NOT( FT_Long*  args )
   {
-    DO_NOT
+    args[0] = !args[0];
   }
 
 
@@ -4138,9 +2824,9 @@
   /* Stack:        f26.6 f26.6 --> f26.6                                   */
   /*                                                                       */
   static void
-  Ins_ADD( INS_ARG )
+  Ins_ADD( FT_Long*  args )
   {
-    DO_ADD
+    args[0] += args[1];
   }
 
 
@@ -4151,9 +2837,9 @@
   /* Stack:        f26.6 f26.6 --> f26.6                                   */
   /*                                                                       */
   static void
-  Ins_SUB( INS_ARG )
+  Ins_SUB( FT_Long*  args )
   {
-    DO_SUB
+    args[0] -= args[1];
   }
 
 
@@ -4164,9 +2850,13 @@
   /* Stack:        f26.6 f26.6 --> f26.6                                   */
   /*                                                                       */
   static void
-  Ins_DIV( INS_ARG )
+  Ins_DIV( TT_ExecContext  exc,
+           FT_Long*        args )
   {
-    DO_DIV
+    if ( args[1] == 0 )
+      exc->error = FT_THROW( Divide_By_Zero );
+    else
+      args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
   }
 
 
@@ -4177,9 +2867,9 @@
   /* Stack:        f26.6 f26.6 --> f26.6                                   */
   /*                                                                       */
   static void
-  Ins_MUL( INS_ARG )
+  Ins_MUL( FT_Long*  args )
   {
-    DO_MUL
+    args[0] = FT_MulDiv( args[0], args[1], 64L );
   }
 
 
@@ -4190,9 +2880,9 @@
   /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_ABS( INS_ARG )
+  Ins_ABS( FT_Long*  args )
   {
-    DO_ABS
+    args[0] = FT_ABS( args[0] );
   }
 
 
@@ -4200,12 +2890,12 @@
   /*                                                                       */
   /* NEG[]:        NEGate                                                  */
   /* Opcode range: 0x65                                                    */
-  /* Stack: f26.6 --> f26.6                                                */
+  /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_NEG( INS_ARG )
+  Ins_NEG( FT_Long*  args )
   {
-    DO_NEG
+    args[0] = -args[0];
   }
 
 
@@ -4216,9 +2906,9 @@
   /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_FLOOR( INS_ARG )
+  Ins_FLOOR( FT_Long*  args )
   {
-    DO_FLOOR
+    args[0] = FT_PIX_FLOOR( args[0] );
   }
 
 
@@ -4229,9 +2919,9 @@
   /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_CEILING( INS_ARG )
+  Ins_CEILING( FT_Long*  args )
   {
-    DO_CEILING
+    args[0] = FT_PIX_CEIL( args[0] );
   }
 
 
@@ -4242,9 +2932,42 @@
   /* Stack:        uint32 --> uint32                                       */
   /*                                                                       */
   static void
-  Ins_RS( INS_ARG )
+  Ins_RS( TT_ExecContext  exc,
+          FT_Long*        args )
   {
-    DO_RS
+    FT_ULong  I = (FT_ULong)args[0];
+
+
+    if ( BOUNDSL( I, exc->storeSize ) )
+    {
+      if ( exc->pedantic_hinting )
+        ARRAY_BOUND_ERROR;
+      else
+        args[0] = 0;
+    }
+    else
+    {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      /* subpixel hinting - avoid Typeman Dstroke and */
+      /* IStroke and Vacuform rounds                  */
+      if ( SUBPIXEL_HINTING_INFINALITY                 &&
+           exc->ignore_x_mode                          &&
+           ( ( I == 24                             &&
+               ( exc->face->sph_found_func_flags &
+                 ( SPH_FDEF_SPACING_1 |
+                   SPH_FDEF_SPACING_2 )          ) ) ||
+             ( I == 22                      &&
+               ( exc->sph_in_func_flags   &
+                 SPH_FDEF_TYPEMAN_STROKES ) )        ||
+             ( I == 8                              &&
+               ( exc->face->sph_found_func_flags &
+                 SPH_FDEF_VACUFORM_ROUND_1       ) &&
+               exc->iup_called                     ) ) )
+        args[0] = 0;
+      else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+        args[0] = exc->storage[I];
+    }
   }
 
 
@@ -4255,9 +2978,19 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_WS( INS_ARG )
+  Ins_WS( TT_ExecContext  exc,
+          FT_Long*        args )
   {
-    DO_WS
+    FT_ULong  I = (FT_ULong)args[0];
+
+
+    if ( BOUNDSL( I, exc->storeSize ) )
+    {
+      if ( exc->pedantic_hinting )
+        ARRAY_BOUND_ERROR;
+    }
+    else
+      exc->storage[I] = args[1];
   }
 
 
@@ -4268,9 +3001,19 @@
   /* Stack:        f26.6 uint32 -->                                        */
   /*                                                                       */
   static void
-  Ins_WCVTP( INS_ARG )
+  Ins_WCVTP( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    DO_WCVTP
+    FT_ULong  I = (FT_ULong)args[0];
+
+
+    if ( BOUNDSL( I, exc->cvtSize ) )
+    {
+      if ( exc->pedantic_hinting )
+        ARRAY_BOUND_ERROR;
+    }
+    else
+      exc->func_write_cvt( exc, I, args[1] );
   }
 
 
@@ -4281,9 +3024,19 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_WCVTF( INS_ARG )
+  Ins_WCVTF( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    DO_WCVTF
+    FT_ULong  I = (FT_ULong)args[0];
+
+
+    if ( BOUNDSL( I, exc->cvtSize ) )
+    {
+      if ( exc->pedantic_hinting )
+        ARRAY_BOUND_ERROR;
+    }
+    else
+      exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale );
   }
 
 
@@ -4294,9 +3047,21 @@
   /* Stack:        uint32 --> f26.6                                        */
   /*                                                                       */
   static void
-  Ins_RCVT( INS_ARG )
+  Ins_RCVT( TT_ExecContext  exc,
+            FT_Long*        args )
   {
-    DO_RCVT
+    FT_ULong  I = (FT_ULong)args[0];
+
+
+    if ( BOUNDSL( I, exc->cvtSize ) )
+    {
+      if ( exc->pedantic_hinting )
+        ARRAY_BOUND_ERROR;
+      else
+        args[0] = 0;
+    }
+    else
+      args[0] = exc->func_read_cvt( exc, I );
   }
 
 
@@ -4307,7 +3072,7 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_AA( INS_ARG )
+  Ins_AA( void )
   {
     /* intentionally no longer supported */
   }
@@ -4322,9 +3087,9 @@
   /* Note: The original instruction pops a value from the stack.           */
   /*                                                                       */
   static void
-  Ins_DEBUG( INS_ARG )
+  Ins_DEBUG( TT_ExecContext  exc )
   {
-    DO_DEBUG
+    exc->error = FT_THROW( Debug_OpCode );
   }
 
 
@@ -4335,9 +3100,13 @@
   /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_ROUND( INS_ARG )
+  Ins_ROUND( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    DO_ROUND
+    args[0] = exc->func_round(
+                exc,
+                args[0],
+                exc->tt_metrics.compensations[exc->opcode - 0x68] );
   }
 
 
@@ -4348,48 +3117,44 @@
   /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
-  Ins_NROUND( INS_ARG )
+  Ins_NROUND( TT_ExecContext  exc,
+              FT_Long*        args )
   {
-    DO_NROUND
+    args[0] = Round_None(
+                exc,
+                args[0],
+                exc->tt_metrics.compensations[exc->opcode - 0x6C] );
   }
 
 
   /*************************************************************************/
   /*                                                                       */
   /* MAX[]:        MAXimum                                                 */
-  /* Opcode range: 0x68                                                    */
+  /* Opcode range: 0x8B                                                    */
   /* Stack:        int32? int32? --> int32                                 */
   /*                                                                       */
   static void
-  Ins_MAX( INS_ARG )
+  Ins_MAX( FT_Long*  args )
   {
-    DO_MAX
+    if ( args[1] > args[0] )
+      args[0] = args[1];
   }
 
 
   /*************************************************************************/
   /*                                                                       */
   /* MIN[]:        MINimum                                                 */
-  /* Opcode range: 0x69                                                    */
+  /* Opcode range: 0x8C                                                    */
   /* Stack:        int32? int32? --> int32                                 */
   /*                                                                       */
   static void
-  Ins_MIN( INS_ARG )
+  Ins_MIN( FT_Long*  args )
   {
-    DO_MIN
+    if ( args[1] < args[0] )
+      args[0] = args[1];
   }
 
 
-#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The following functions are called as is within the switch statement. */
-  /*                                                                       */
-  /*************************************************************************/
-
-
   /*************************************************************************/
   /*                                                                       */
   /* MINDEX[]:     Move INDEXed element                                    */
@@ -4397,44 +3162,69 @@
   /* Stack:        int32? --> StkElt                                       */
   /*                                                                       */
   static void
-  Ins_MINDEX( INS_ARG )
+  Ins_MINDEX( TT_ExecContext  exc,
+              FT_Long*        args )
   {
     FT_Long  L, K;
 
 
     L = args[0];
 
-    if ( L <= 0 || L > CUR.args )
+    if ( L <= 0 || L > exc->args )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
     }
     else
     {
-      K = CUR.stack[CUR.args - L];
+      K = exc->stack[exc->args - L];
 
-      FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
-                     &CUR.stack[CUR.args - L + 1],
+      FT_ARRAY_MOVE( &exc->stack[exc->args - L    ],
+                     &exc->stack[exc->args - L + 1],
                      ( L - 1 ) );
 
-      CUR.stack[CUR.args - 1] = K;
+      exc->stack[exc->args - 1] = K;
     }
   }
 
 
   /*************************************************************************/
   /*                                                                       */
+  /* CINDEX[]:     Copy INDEXed element                                    */
+  /* Opcode range: 0x25                                                    */
+  /* Stack:        int32 --> StkElt                                        */
+  /*                                                                       */
+  static void
+  Ins_CINDEX( TT_ExecContext  exc,
+              FT_Long*        args )
+  {
+    FT_Long  L;
+
+
+    L = args[0];
+
+    if ( L <= 0 || L > exc->args )
+    {
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
+      args[0] = 0;
+    }
+    else
+      args[0] = exc->stack[exc->args - L];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* ROLL[]:       ROLL top three elements                                 */
   /* Opcode range: 0x8A                                                    */
   /* Stack:        3 * StkElt --> 3 * StkElt                               */
   /*                                                                       */
   static void
-  Ins_ROLL( INS_ARG )
+  Ins_ROLL( FT_Long*  args )
   {
     FT_Long  A, B, C;
 
-    FT_UNUSED_EXEC;
-
 
     A = args[2];
     B = args[1];
@@ -4450,34 +3240,49 @@
   /*                                                                       */
   /* MANAGING THE FLOW OF CONTROL                                          */
   /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
   /*************************************************************************/
 
 
-  static FT_Bool
-  SkipCode( EXEC_OP )
+  /*************************************************************************/
+  /*                                                                       */
+  /* SLOOP[]:      Set LOOP variable                                       */
+  /* Opcode range: 0x17                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SLOOP( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    CUR.IP += CUR.length;
+    if ( args[0] < 0 )
+      exc->error = FT_THROW( Bad_Argument );
+    else
+      exc->GS.loop = args[0];
+  }
 
-    if ( CUR.IP < CUR.codeSize )
+
+  static FT_Bool
+  SkipCode( TT_ExecContext  exc )
+  {
+    exc->IP += exc->length;
+
+    if ( exc->IP < exc->codeSize )
     {
-      CUR.opcode = CUR.code[CUR.IP];
+      exc->opcode = exc->code[exc->IP];
 
-      CUR.length = opcode_length[CUR.opcode];
-      if ( CUR.length < 0 )
+      exc->length = opcode_length[exc->opcode];
+      if ( exc->length < 0 )
       {
-        if ( CUR.IP + 1 >= CUR.codeSize )
+        if ( exc->IP + 1 >= exc->codeSize )
           goto Fail_Overflow;
-        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+        exc->length = 2 - exc->length * exc->code[exc->IP + 1];
       }
 
-      if ( CUR.IP + CUR.length <= CUR.codeSize )
+      if ( exc->IP + exc->length <= exc->codeSize )
         return SUCCESS;
     }
 
   Fail_Overflow:
-    CUR.error = FT_THROW( Code_Overflow );
+    exc->error = FT_THROW( Code_Overflow );
     return FAILURE;
   }
 
@@ -4489,7 +3294,8 @@
   /* Stack:        StkElt -->                                              */
   /*                                                                       */
   static void
-  Ins_IF( INS_ARG )
+  Ins_IF( TT_ExecContext  exc,
+          FT_Long*        args )
   {
     FT_Int   nIfs;
     FT_Bool  Out;
@@ -4503,10 +3309,10 @@
 
     do
     {
-      if ( SKIP_Code() == FAILURE )
+      if ( SkipCode( exc ) == FAILURE )
         return;
 
-      switch ( CUR.opcode )
+      switch ( exc->opcode )
       {
       case 0x58:      /* IF */
         nIfs++;
@@ -4532,21 +3338,19 @@
   /* Stack:        -->                                                     */
   /*                                                                       */
   static void
-  Ins_ELSE( INS_ARG )
+  Ins_ELSE( TT_ExecContext  exc )
   {
     FT_Int  nIfs;
 
-    FT_UNUSED_ARG;
-
 
     nIfs = 1;
 
     do
     {
-      if ( SKIP_Code() == FAILURE )
+      if ( SkipCode( exc ) == FAILURE )
         return;
 
-      switch ( CUR.opcode )
+      switch ( exc->opcode )
       {
       case 0x58:    /* IF */
         nIfs++;
@@ -4562,9 +3366,71 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
+  /* EIF[]:        End IF                                                  */
+  /* Opcode range: 0x59                                                    */
+  /* Stack:        -->                                                     */
   /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
+  static void
+  Ins_EIF( void )
+  {
+    /* nothing to do */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JMPR[]:       JuMP Relative                                           */
+  /* Opcode range: 0x1C                                                    */
+  /* Stack:        int32 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_JMPR( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    if ( args[0] == 0 && exc->args == 0 )
+      exc->error = FT_THROW( Bad_Argument );
+    exc->IP += args[0];
+    if ( exc->IP < 0                                             ||
+         ( exc->callTop > 0                                    &&
+           exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
+      exc->error = FT_THROW( Bad_Argument );
+    exc->step_ins = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROT[]:       Jump Relative On True                                   */
+  /* Opcode range: 0x78                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_JROT( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    if ( args[1] != 0 )
+      Ins_JMPR( exc, args );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROF[]:       Jump Relative On False                                  */
+  /* Opcode range: 0x79                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_JROF( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    if ( args[1] == 0 )
+      Ins_JMPR( exc, args );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
   /*                                                                       */
   /*************************************************************************/
 
@@ -4576,13 +3442,14 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_FDEF( INS_ARG )
+  Ins_FDEF( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_ULong       n;
     TT_DefRecord*  rec;
     TT_DefRecord*  limit;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* arguments to opcodes are skipped by `SKIP_Code' */
     FT_Byte    opcode_pattern[9][12] = {
                  /* #0 inline delta function 1 */
@@ -4680,15 +3547,15 @@
     FT_UShort  opcode_pointer[9] = {  0, 0, 0, 0, 0, 0, 0, 0, 0 };
     FT_UShort  opcode_size[9]    = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
     FT_UShort  i;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
     /* some font programs are broken enough to redefine functions! */
     /* We will then parse the current table.                       */
 
-    rec   = CUR.FDefs;
-    limit = rec + CUR.numFDefs;
-    n     = args[0];
+    rec   = exc->FDefs;
+    limit = rec + exc->numFDefs;
+    n     = (FT_ULong)args[0];
 
     for ( ; rec < limit; rec++ )
     {
@@ -4699,33 +3566,33 @@
     if ( rec == limit )
     {
       /* check that there is enough room for new functions */
-      if ( CUR.numFDefs >= CUR.maxFDefs )
+      if ( exc->numFDefs >= exc->maxFDefs )
       {
-        CUR.error = FT_THROW( Too_Many_Function_Defs );
+        exc->error = FT_THROW( Too_Many_Function_Defs );
         return;
       }
-      CUR.numFDefs++;
+      exc->numFDefs++;
     }
 
     /* Although FDEF takes unsigned 32-bit integer,  */
     /* func # must be within unsigned 16-bit integer */
     if ( n > 0xFFFFU )
     {
-      CUR.error = FT_THROW( Too_Many_Function_Defs );
+      exc->error = FT_THROW( Too_Many_Function_Defs );
       return;
     }
 
-    rec->range          = CUR.curRange;
+    rec->range          = exc->curRange;
     rec->opc            = (FT_UInt16)n;
-    rec->start          = CUR.IP + 1;
+    rec->start          = exc->IP + 1;
     rec->active         = TRUE;
     rec->inline_delta   = FALSE;
     rec->sph_fdef_flags = 0x0000;
 
-    if ( n > CUR.maxFunc )
-      CUR.maxFunc = (FT_UInt16)n;
+    if ( n > exc->maxFunc )
+      exc->maxFunc = (FT_UInt16)n;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* We don't know for sure these are typeman functions, */
     /* however they are only active when RS 22 is called   */
     if ( n >= 64 && n <= 66 )
@@ -4735,37 +3602,37 @@
     /* Now skip the whole function definition. */
     /* We don't allow nested IDEFS & FDEFs.    */
 
-    while ( SKIP_Code() == SUCCESS )
+    while ( SkipCode( exc ) == SUCCESS )
     {
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-      if ( SUBPIXEL_HINTING )
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
-          if ( opcode_pointer[i] < opcode_size[i]                 &&
-               CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+          if ( opcode_pointer[i] < opcode_size[i]                  &&
+               exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
           {
             opcode_pointer[i] += 1;
 
             if ( opcode_pointer[i] == opcode_size[i] )
             {
-              FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
+              FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
                           i, n,
-                          CUR.face->root.family_name,
-                          CUR.face->root.style_name ));
+                          exc->face->root.family_name,
+                          exc->face->root.style_name ));
 
               switch ( i )
               {
               case 0:
-                rec->sph_fdef_flags            |= SPH_FDEF_INLINE_DELTA_1;
-                CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
+                rec->sph_fdef_flags             |= SPH_FDEF_INLINE_DELTA_1;
+                exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
                 break;
 
               case 1:
-                rec->sph_fdef_flags            |= SPH_FDEF_INLINE_DELTA_2;
-                CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
+                rec->sph_fdef_flags             |= SPH_FDEF_INLINE_DELTA_2;
+                exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
                 break;
 
               case 2:
@@ -4773,8 +3640,8 @@
                 {
                   /* needs to be implemented still */
                 case 58:
-                  rec->sph_fdef_flags            |= SPH_FDEF_DIAGONAL_STROKE;
-                  CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
+                  rec->sph_fdef_flags             |= SPH_FDEF_DIAGONAL_STROKE;
+                  exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
                 }
                 break;
 
@@ -4782,15 +3649,15 @@
                 switch ( n )
                 {
                 case 0:
-                  rec->sph_fdef_flags            |= SPH_FDEF_VACUFORM_ROUND_1;
-                  CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+                  rec->sph_fdef_flags             |= SPH_FDEF_VACUFORM_ROUND_1;
+                  exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
                 }
                 break;
 
               case 4:
                 /* probably not necessary to detect anymore */
-                rec->sph_fdef_flags            |= SPH_FDEF_TTFAUTOHINT_1;
-                CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
+                rec->sph_fdef_flags             |= SPH_FDEF_TTFAUTOHINT_1;
+                exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
                 break;
 
               case 5:
@@ -4802,8 +3669,8 @@
                 case 4:
                 case 7:
                 case 8:
-                  rec->sph_fdef_flags            |= SPH_FDEF_SPACING_1;
-                  CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
+                  rec->sph_fdef_flags             |= SPH_FDEF_SPACING_1;
+                  exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
                 }
                 break;
 
@@ -4816,20 +3683,20 @@
                 case 4:
                 case 7:
                 case 8:
-                  rec->sph_fdef_flags            |= SPH_FDEF_SPACING_2;
-                  CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
+                  rec->sph_fdef_flags             |= SPH_FDEF_SPACING_2;
+                  exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
                 }
                 break;
 
                case 7:
-                 rec->sph_fdef_flags            |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-                 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 rec->sph_fdef_flags             |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
                  break;
 
                case 8:
 #if 0
-                 rec->sph_fdef_flags            |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-                 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 rec->sph_fdef_flags             |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
 #endif
                  break;
               }
@@ -4842,22 +3709,22 @@
         }
 
         /* Set sph_compatibility_mode only when deltas are detected */
-        CUR.face->sph_compatibility_mode =
-          ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
-            ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
+        exc->face->sph_compatibility_mode =
+          ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
+            ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-      switch ( CUR.opcode )
+      switch ( exc->opcode )
       {
       case 0x89:    /* IDEF */
       case 0x2C:    /* FDEF */
-        CUR.error = FT_THROW( Nested_DEFS );
+        exc->error = FT_THROW( Nested_DEFS );
         return;
 
       case 0x2D:   /* ENDF */
-        rec->end = CUR.IP;
+        rec->end = exc->IP;
         return;
       }
     }
@@ -4871,40 +3738,37 @@
   /* Stack:        -->                                                     */
   /*                                                                       */
   static void
-  Ins_ENDF( INS_ARG )
+  Ins_ENDF( TT_ExecContext  exc )
   {
     TT_CallRec*  pRec;
 
-    FT_UNUSED_ARG;
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    exc->sph_in_func_flags = 0x0000;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    CUR.sph_in_func_flags = 0x0000;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
+    if ( exc->callTop <= 0 )     /* We encountered an ENDF without a call */
     {
-      CUR.error = FT_THROW( ENDF_In_Exec_Stream );
+      exc->error = FT_THROW( ENDF_In_Exec_Stream );
       return;
     }
 
-    CUR.callTop--;
+    exc->callTop--;
 
-    pRec = &CUR.callStack[CUR.callTop];
+    pRec = &exc->callStack[exc->callTop];
 
     pRec->Cur_Count--;
 
-    CUR.step_ins = FALSE;
+    exc->step_ins = FALSE;
 
     if ( pRec->Cur_Count > 0 )
     {
-      CUR.callTop++;
-      CUR.IP = pRec->Def->start;
+      exc->callTop++;
+      exc->IP = pRec->Def->start;
     }
     else
       /* Loop through the current function */
-      INS_Goto_CodeRange( pRec->Caller_Range,
-                          pRec->Caller_IP );
+      Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP );
 
     /* Exit the current call frame.                      */
 
@@ -4923,7 +3787,8 @@
   /* Stack:        uint32? -->                                             */
   /*                                                                       */
   static void
-  Ins_CALL( INS_ARG )
+  Ins_CALL( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_ULong       F;
     TT_CallRec*    pCrec;
@@ -4932,28 +3797,28 @@
 
     /* first of all, check the index */
 
-    F = args[0];
-    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
+    F = (FT_ULong)args[0];
+    if ( BOUNDSL( F, exc->maxFunc + 1 ) )
       goto Fail;
 
     /* Except for some old Apple fonts, all functions in a TrueType */
     /* font are defined in increasing order, starting from 0.  This */
     /* means that we normally have                                  */
     /*                                                              */
-    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
-    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*    exc->maxFunc+1 == exc->numFDefs                           */
+    /*    exc->FDefs[n].opc == n for n in 0..exc->maxFunc           */
     /*                                                              */
     /* If this isn't true, we need to look up the function table.   */
 
-    def = CUR.FDefs + F;
-    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    def = exc->FDefs + F;
+    if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
     {
       /* look up the FDefs table */
       TT_DefRecord*  limit;
 
 
-      def   = CUR.FDefs;
-      limit = def + CUR.numFDefs;
+      def   = exc->FDefs;
+      limit = def + exc->numFDefs;
 
       while ( def < limit && def->opc != F )
         def++;
@@ -4966,42 +3831,41 @@
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                              &&
-         CUR.ignore_x_mode                                             &&
-         ( ( CUR.iup_called                                        &&
-             ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
-           ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )       ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                                    &&
+         exc->ignore_x_mode                                             &&
+         ( ( exc->iup_called                                        &&
+             ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
+           ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )        ) )
       goto Fail;
     else
-      CUR.sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      exc->sph_in_func_flags = def->sph_fdef_flags;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check the call stack */
-    if ( CUR.callTop >= CUR.callSize )
+    if ( exc->callTop >= exc->callSize )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
-    pCrec = CUR.callStack + CUR.callTop;
+    pCrec = exc->callStack + exc->callTop;
 
-    pCrec->Caller_Range = CUR.curRange;
-    pCrec->Caller_IP    = CUR.IP + 1;
+    pCrec->Caller_Range = exc->curRange;
+    pCrec->Caller_IP    = exc->IP + 1;
     pCrec->Cur_Count    = 1;
     pCrec->Def          = def;
 
-    CUR.callTop++;
+    exc->callTop++;
 
-    INS_Goto_CodeRange( def->range,
-                        def->start );
+    Ins_Goto_CodeRange( exc, def->range, def->start );
 
-    CUR.step_ins = FALSE;
+    exc->step_ins = FALSE;
 
     return;
 
   Fail:
-    CUR.error = FT_THROW( Invalid_Reference );
+    exc->error = FT_THROW( Invalid_Reference );
   }
 
 
@@ -5012,7 +3876,8 @@
   /* Stack:        uint32? Eint16? -->                                     */
   /*                                                                       */
   static void
-  Ins_LOOPCALL( INS_ARG )
+  Ins_LOOPCALL( TT_ExecContext  exc,
+                FT_Long*        args )
   {
     FT_ULong       F;
     TT_CallRec*    pCrec;
@@ -5020,28 +3885,28 @@
 
 
     /* first of all, check the index */
-    F = args[1];
-    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
+    F = (FT_ULong)args[1];
+    if ( BOUNDSL( F, exc->maxFunc + 1 ) )
       goto Fail;
 
     /* Except for some old Apple fonts, all functions in a TrueType */
     /* font are defined in increasing order, starting from 0.  This */
     /* means that we normally have                                  */
     /*                                                              */
-    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
-    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*    exc->maxFunc+1 == exc->numFDefs                           */
+    /*    exc->FDefs[n].opc == n for n in 0..exc->maxFunc           */
     /*                                                              */
     /* If this isn't true, we need to look up the function table.   */
 
-    def = CUR.FDefs + F;
-    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    def = exc->FDefs + F;
+    if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
     {
       /* look up the FDefs table */
       TT_DefRecord*  limit;
 
 
-      def   = CUR.FDefs;
-      limit = def + CUR.numFDefs;
+      def   = exc->FDefs;
+      limit = def + exc->numFDefs;
 
       while ( def < limit && def->opc != F )
         def++;
@@ -5054,42 +3919,42 @@
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                    &&
-         CUR.ignore_x_mode                                   &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                         &&
+         exc->ignore_x_mode                                  &&
          ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
       goto Fail;
     else
-      CUR.sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      exc->sph_in_func_flags = def->sph_fdef_flags;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check stack */
-    if ( CUR.callTop >= CUR.callSize )
+    if ( exc->callTop >= exc->callSize )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
     if ( args[0] > 0 )
     {
-      pCrec = CUR.callStack + CUR.callTop;
+      pCrec = exc->callStack + exc->callTop;
 
-      pCrec->Caller_Range = CUR.curRange;
-      pCrec->Caller_IP    = CUR.IP + 1;
+      pCrec->Caller_Range = exc->curRange;
+      pCrec->Caller_IP    = exc->IP + 1;
       pCrec->Cur_Count    = (FT_Int)args[0];
       pCrec->Def          = def;
 
-      CUR.callTop++;
+      exc->callTop++;
 
-      INS_Goto_CodeRange( def->range, def->start );
+      Ins_Goto_CodeRange( exc, def->range, def->start );
 
-      CUR.step_ins = FALSE;
+      exc->step_ins = FALSE;
     }
 
     return;
 
   Fail:
-    CUR.error = FT_THROW( Invalid_Reference );
+    exc->error = FT_THROW( Invalid_Reference );
   }
 
 
@@ -5100,7 +3965,8 @@
   /* Stack:        Eint8 -->                                               */
   /*                                                                       */
   static void
-  Ins_IDEF( INS_ARG )
+  Ins_IDEF( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     TT_DefRecord*  def;
     TT_DefRecord*  limit;
@@ -5108,8 +3974,8 @@
 
     /*  First of all, look for the same function in our table */
 
-    def   = CUR.IDefs;
-    limit = def + CUR.numIDefs;
+    def   = exc->IDefs;
+    limit = def + exc->numIDefs;
 
     for ( ; def < limit; def++ )
       if ( def->opc == (FT_ULong)args[0] )
@@ -5118,41 +3984,42 @@
     if ( def == limit )
     {
       /* check that there is enough room for a new instruction */
-      if ( CUR.numIDefs >= CUR.maxIDefs )
+      if ( exc->numIDefs >= exc->maxIDefs )
       {
-        CUR.error = FT_THROW( Too_Many_Instruction_Defs );
+        exc->error = FT_THROW( Too_Many_Instruction_Defs );
         return;
       }
-      CUR.numIDefs++;
+      exc->numIDefs++;
     }
 
     /* opcode must be unsigned 8-bit integer */
     if ( 0 > args[0] || args[0] > 0x00FF )
     {
-      CUR.error = FT_THROW( Too_Many_Instruction_Defs );
+      exc->error = FT_THROW( Too_Many_Instruction_Defs );
       return;
     }
 
     def->opc    = (FT_Byte)args[0];
-    def->start  = CUR.IP + 1;
-    def->range  = CUR.curRange;
+    def->start  = exc->IP + 1;
+    def->range  = exc->curRange;
     def->active = TRUE;
 
-    if ( (FT_ULong)args[0] > CUR.maxIns )
-      CUR.maxIns = (FT_Byte)args[0];
+    if ( (FT_ULong)args[0] > exc->maxIns )
+      exc->maxIns = (FT_Byte)args[0];
 
     /* Now skip the whole function definition. */
     /* We don't allow nested IDEFs & FDEFs.    */
 
-    while ( SKIP_Code() == SUCCESS )
+    while ( SkipCode( exc ) == SUCCESS )
     {
-      switch ( CUR.opcode )
+      switch ( exc->opcode )
       {
       case 0x89:   /* IDEF */
       case 0x2C:   /* FDEF */
-        CUR.error = FT_THROW( Nested_DEFS );
+        exc->error = FT_THROW( Nested_DEFS );
         return;
       case 0x2D:   /* ENDF */
+        def->end = exc->IP;
         return;
       }
     }
@@ -5163,8 +4030,6 @@
   /*                                                                       */
   /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
   /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
   /*************************************************************************/
 
 
@@ -5175,23 +4040,24 @@
   /* Stack:        --> uint32...                                           */
   /*                                                                       */
   static void
-  Ins_NPUSHB( INS_ARG )
+  Ins_NPUSHB( TT_ExecContext  exc,
+              FT_Long*        args )
   {
     FT_UShort  L, K;
 
 
-    L = (FT_UShort)CUR.code[CUR.IP + 1];
+    L = (FT_UShort)exc->code[exc->IP + 1];
 
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
     for ( K = 1; K <= L; K++ )
-      args[K - 1] = CUR.code[CUR.IP + K + 1];
+      args[K - 1] = exc->code[exc->IP + K + 1];
 
-    CUR.new_top += L;
+    exc->new_top += L;
   }
 
 
@@ -5202,26 +4068,27 @@
   /* Stack:        --> int32...                                            */
   /*                                                                       */
   static void
-  Ins_NPUSHW( INS_ARG )
+  Ins_NPUSHW( TT_ExecContext  exc,
+              FT_Long*        args )
   {
     FT_UShort  L, K;
 
 
-    L = (FT_UShort)CUR.code[CUR.IP + 1];
+    L = (FT_UShort)exc->code[exc->IP + 1];
 
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
-    CUR.IP += 2;
+    exc->IP += 2;
 
     for ( K = 0; K < L; K++ )
-      args[K] = GET_ShortIns();
+      args[K] = GetShortIns( exc );
 
-    CUR.step_ins = FALSE;
-    CUR.new_top += L;
+    exc->step_ins = FALSE;
+    exc->new_top += L;
   }
 
 
@@ -5232,21 +4099,22 @@
   /* Stack:        --> uint32...                                           */
   /*                                                                       */
   static void
-  Ins_PUSHB( INS_ARG )
+  Ins_PUSHB( TT_ExecContext  exc,
+             FT_Long*        args )
   {
     FT_UShort  L, K;
 
 
-    L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
+    L = (FT_UShort)( exc->opcode - 0xB0 + 1 );
 
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
     for ( K = 1; K <= L; K++ )
-      args[K - 1] = CUR.code[CUR.IP + K];
+      args[K - 1] = exc->code[exc->IP + K];
   }
 
 
@@ -5257,25 +4125,26 @@
   /* Stack:        --> int32...                                            */
   /*                                                                       */
   static void
-  Ins_PUSHW( INS_ARG )
+  Ins_PUSHW( TT_ExecContext  exc,
+             FT_Long*        args )
   {
     FT_UShort  L, K;
 
 
-    L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
+    L = (FT_UShort)( exc->opcode - 0xB8 + 1 );
 
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
     {
-      CUR.error = FT_THROW( Stack_Overflow );
+      exc->error = FT_THROW( Stack_Overflow );
       return;
     }
 
-    CUR.IP++;
+    exc->IP++;
 
     for ( K = 0; K < L; K++ )
-      args[K] = GET_ShortIns();
+      args[K] = GetShortIns( exc );
 
-    CUR.step_ins = FALSE;
+    exc->step_ins = FALSE;
   }
 
 
@@ -5283,11 +4152,526 @@
   /*                                                                       */
   /* MANAGING THE GRAPHICS STATE                                           */
   /*                                                                       */
-  /*  Instructions appear in the specs' order.                             */
-  /*                                                                       */
   /*************************************************************************/
 
 
+  static FT_Bool
+  Ins_SxVTL( TT_ExecContext  exc,
+             FT_UShort       aIdx1,
+             FT_UShort       aIdx2,
+             FT_UnitVector*  Vec )
+  {
+    FT_Long     A, B, C;
+    FT_Vector*  p1;
+    FT_Vector*  p2;
+
+    FT_Byte  opcode = exc->opcode;
+
+
+    if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
+         BOUNDS( aIdx2, exc->zp1.n_points ) )
+    {
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
+      return FAILURE;
+    }
+
+    p1 = exc->zp1.cur + aIdx2;
+    p2 = exc->zp2.cur + aIdx1;
+
+    A = p1->x - p2->x;
+    B = p1->y - p2->y;
+
+    /* If p1 == p2, SPvTL and SFvTL behave the same as */
+    /* SPvTCA[X] and SFvTCA[X], respectively.          */
+    /*                                                 */
+    /* Confirmed by Greg Hitchcock.                    */
+
+    if ( A == 0 && B == 0 )
+    {
+      A      = 0x4000;
+      opcode = 0;
+    }
+
+    if ( ( opcode & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    Normalize( A, B, Vec );
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
+  /* Opcode range: 0x00-0x01                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  /* SPvTCA[a]:    Set PVector to Coordinate Axis                          */
+  /* Opcode range: 0x02-0x03                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  /* SFvTCA[a]:    Set FVector to Coordinate Axis                          */
+  /* Opcode range: 0x04-0x05                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SxyTCA( TT_ExecContext  exc )
+  {
+    FT_Short  AA, BB;
+
+    FT_Byte  opcode = exc->opcode;
+
+
+    AA = (FT_Short)( ( opcode & 1 ) << 14 );
+    BB = (FT_Short)( AA ^ 0x4000 );
+
+    if ( opcode < 4 )
+    {
+      exc->GS.projVector.x = AA;
+      exc->GS.projVector.y = BB;
+
+      exc->GS.dualVector.x = AA;
+      exc->GS.dualVector.y = BB;
+    }
+
+    if ( ( opcode & 2 ) == 0 )
+    {
+      exc->GS.freeVector.x = AA;
+      exc->GS.freeVector.y = BB;
+    }
+
+    Compute_Funcs( exc );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPvTL[a]:     Set PVector To Line                                     */
+  /* Opcode range: 0x06-0x07                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_SPVTL( TT_ExecContext  exc,
+             FT_Long*        args )
+  {
+    if ( Ins_SxVTL( exc,
+                    (FT_UShort)args[1],
+                    (FT_UShort)args[0],
+                    &exc->GS.projVector ) == SUCCESS )
+    {
+      exc->GS.dualVector = exc->GS.projVector;
+      Compute_Funcs( exc );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFvTL[a]:     Set FVector To Line                                     */
+  /* Opcode range: 0x08-0x09                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_SFVTL( TT_ExecContext  exc,
+             FT_Long*        args )
+  {
+    if ( Ins_SxVTL( exc,
+                    (FT_UShort)args[1],
+                    (FT_UShort)args[0],
+                    &exc->GS.freeVector ) == SUCCESS )
+    {
+      Compute_Funcs( exc );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFvTPv[]:     Set FVector To PVector                                  */
+  /* Opcode range: 0x0E                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SFVTPV( TT_ExecContext  exc )
+  {
+    exc->GS.freeVector = exc->GS.projVector;
+    Compute_Funcs( exc );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPvFS[]:      Set PVector From Stack                                  */
+  /* Opcode range: 0x0A                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static void
+  Ins_SPVFS( TT_ExecContext  exc,
+             FT_Long*        args )
+  {
+    FT_Short  S;
+    FT_Long   X, Y;
+
+
+    /* Only use low 16bits, then sign extend */
+    S = (FT_Short)args[1];
+    Y = (FT_Long)S;
+    S = (FT_Short)args[0];
+    X = (FT_Long)S;
+
+    Normalize( X, Y, &exc->GS.projVector );
+
+    exc->GS.dualVector = exc->GS.projVector;
+    Compute_Funcs( exc );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFvFS[]:      Set FVector From Stack                                  */
+  /* Opcode range: 0x0B                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static void
+  Ins_SFVFS( TT_ExecContext  exc,
+             FT_Long*        args )
+  {
+    FT_Short  S;
+    FT_Long   X, Y;
+
+
+    /* Only use low 16bits, then sign extend */
+    S = (FT_Short)args[1];
+    Y = (FT_Long)S;
+    S = (FT_Short)args[0];
+    X = S;
+
+    Normalize( X, Y, &exc->GS.freeVector );
+    Compute_Funcs( exc );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GPv[]:        Get Projection Vector                                   */
+  /* Opcode range: 0x0C                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static void
+  Ins_GPV( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    args[0] = exc->GS.projVector.x;
+    args[1] = exc->GS.projVector.y;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GFv[]:        Get Freedom Vector                                      */
+  /* Opcode range: 0x0D                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static void
+  Ins_GFV( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    args[0] = exc->GS.freeVector.x;
+    args[1] = exc->GS.freeVector.y;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP0[]:       Set Reference Point 0                                   */
+  /* Opcode range: 0x10                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP0( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    exc->GS.rp0 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP1[]:       Set Reference Point 1                                   */
+  /* Opcode range: 0x11                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP1( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    exc->GS.rp1 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP2[]:       Set Reference Point 2                                   */
+  /* Opcode range: 0x12                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP2( TT_ExecContext  exc,
+            FT_Long*        args )
+  {
+    exc->GS.rp2 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SMD[]:        Set Minimum Distance                                    */
+  /* Opcode range: 0x1A                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SMD( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    exc->GS.minimum_distance = args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCVTCI[]:     Set Control Value Table Cut In                          */
+  /* Opcode range: 0x1D                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SCVTCI( TT_ExecContext  exc,
+              FT_Long*        args )
+  {
+    exc->GS.control_value_cutin = (FT_F26Dot6)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSWCI[]:      Set Single Width Cut In                                 */
+  /* Opcode range: 0x1E                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SSWCI( TT_ExecContext  exc,
+             FT_Long*        args )
+  {
+    exc->GS.single_width_cutin = (FT_F26Dot6)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSW[]:        Set Single Width                                        */
+  /* Opcode range: 0x1F                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SSW( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    exc->GS.single_width_value = FT_MulFix( args[0],
+                                            exc->tt_metrics.scale );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPON[]:     Set auto-FLIP to ON                                     */
+  /* Opcode range: 0x4D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_FLIPON( TT_ExecContext  exc )
+  {
+    exc->GS.auto_flip = TRUE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
+  /* Opcode range: 0x4E                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_FLIPOFF( TT_ExecContext  exc )
+  {
+    exc->GS.auto_flip = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SANGW[]:      Set ANGle Weight                                        */
+  /* Opcode range: 0x7E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SANGW( void )
+  {
+    /* instruction not supported anymore */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDB[]:        Set Delta Base                                          */
+  /* Opcode range: 0x5E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SDB( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    exc->GS.delta_base = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDS[]:        Set Delta Shift                                         */
+  /* Opcode range: 0x5F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SDS( TT_ExecContext  exc,
+           FT_Long*        args )
+  {
+    if ( (FT_ULong)args[0] > 6UL )
+      exc->error = FT_THROW( Bad_Argument );
+    else
+      exc->GS.delta_shift = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTHG[]:       Round To Half Grid                                      */
+  /* Opcode range: 0x19                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTHG( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_To_Half_Grid;
+    exc->func_round     = (TT_Round_Func)Round_To_Half_Grid;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTG[]:        Round To Grid                                           */
+  /* Opcode range: 0x18                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTG( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_To_Grid;
+    exc->func_round     = (TT_Round_Func)Round_To_Grid;
+  }
+
+
+  /*************************************************************************/
+  /* RTDG[]:       Round To Double Grid                                    */
+  /* Opcode range: 0x3D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTDG( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_To_Double_Grid;
+    exc->func_round     = (TT_Round_Func)Round_To_Double_Grid;
+  }
+
+
+  /*************************************************************************/
+  /* RUTG[]:       Round Up To Grid                                        */
+  /* Opcode range: 0x7C                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RUTG( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_Up_To_Grid;
+    exc->func_round     = (TT_Round_Func)Round_Up_To_Grid;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RDTG[]:       Round Down To Grid                                      */
+  /* Opcode range: 0x7D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RDTG( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_Down_To_Grid;
+    exc->func_round     = (TT_Round_Func)Round_Down_To_Grid;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROFF[]:       Round OFF                                               */
+  /* Opcode range: 0x7A                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_ROFF( TT_ExecContext  exc )
+  {
+    exc->GS.round_state = TT_Round_Off;
+    exc->func_round     = (TT_Round_Func)Round_None;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SROUND[]:     Super ROUND                                             */
+  /* Opcode range: 0x76                                                    */
+  /* Stack:        Eint8 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SROUND( TT_ExecContext  exc,
+              FT_Long*        args )
+  {
+    SetSuperRound( exc, 0x4000, args[0] );
+
+    exc->GS.round_state = TT_Round_Super;
+    exc->func_round     = (TT_Round_Func)Round_Super;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
+  /* Opcode range: 0x77                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_S45ROUND( TT_ExecContext  exc,
+                FT_Long*        args )
+  {
+    SetSuperRound( exc, 0x2D41, args[0] );
+
+    exc->GS.round_state = TT_Round_Super_45;
+    exc->func_round     = (TT_Round_Func)Round_Super_45;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* GC[a]:        Get Coordinate projected onto                           */
@@ -5298,7 +4682,8 @@
   /*      along the dual projection vector!                                */
   /*                                                                       */
   static void
-  Ins_GC( INS_ARG )
+  Ins_GC( TT_ExecContext  exc,
+          FT_Long*        args )
   {
     FT_ULong    L;
     FT_F26Dot6  R;
@@ -5306,18 +4691,18 @@
 
     L = (FT_ULong)args[0];
 
-    if ( BOUNDSL( L, CUR.zp2.n_points ) )
+    if ( BOUNDSL( L, exc->zp2.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       R = 0;
     }
     else
     {
-      if ( CUR.opcode & 1 )
-        R = CUR_fast_dualproj( &CUR.zp2.org[L] );
+      if ( exc->opcode & 1 )
+        R = FAST_DUALPROJ( &exc->zp2.org[L] );
       else
-        R = CUR_fast_project( &CUR.zp2.cur[L] );
+        R = FAST_PROJECT( &exc->zp2.cur[L] );
     }
 
     args[0] = R;
@@ -5335,7 +4720,8 @@
   /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
   /*                                                                       */
   static void
-  Ins_SCFS( INS_ARG )
+  Ins_SCFS( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_Long    K;
     FT_UShort  L;
@@ -5343,21 +4729,21 @@
 
     L = (FT_UShort)args[0];
 
-    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    if ( BOUNDS( L, exc->zp2.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    K = CUR_fast_project( &CUR.zp2.cur[L] );
+    K = FAST_PROJECT( &exc->zp2.cur[L] );
 
-    CUR_Func_move( &CUR.zp2, L, args[1] - K );
+    exc->func_move( exc, &exc->zp2, L, args[1] - K );
 
     /* UNDOCUMENTED!  The MS rasterizer does that with */
     /* twilight points (confirmed by Greg Hitchcock)   */
-    if ( CUR.GS.gep2 == 0 )
-      CUR.zp2.org[L] = CUR.zp2.cur[L];
+    if ( exc->GS.gep2 == 0 )
+      exc->zp2.org[L] = exc->zp2.cur[L];
   }
 
 
@@ -5377,7 +4763,8 @@
   /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1!                   */
   /*                                                                       */
   static void
-  Ins_MD( INS_ARG )
+  Ins_MD( TT_ExecContext  exc,
+          FT_Long*        args )
   {
     FT_UShort   K, L;
     FT_F26Dot6  D;
@@ -5386,61 +4773,62 @@
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
-    if ( BOUNDS( L, CUR.zp0.n_points ) ||
-         BOUNDS( K, CUR.zp1.n_points ) )
+    if ( BOUNDS( L, exc->zp0.n_points ) ||
+         BOUNDS( K, exc->zp1.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       D = 0;
     }
     else
     {
-      if ( CUR.opcode & 1 )
-        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+      if ( exc->opcode & 1 )
+        D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K );
       else
       {
         /* XXX: UNDOCUMENTED: twilight zone special case */
 
-        if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
+        if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
         {
-          FT_Vector*  vec1 = CUR.zp0.org + L;
-          FT_Vector*  vec2 = CUR.zp1.org + K;
+          FT_Vector*  vec1 = exc->zp0.org + L;
+          FT_Vector*  vec2 = exc->zp1.org + K;
 
 
-          D = CUR_Func_dualproj( vec1, vec2 );
+          D = DUALPROJ( vec1, vec2 );
         }
         else
         {
-          FT_Vector*  vec1 = CUR.zp0.orus + L;
-          FT_Vector*  vec2 = CUR.zp1.orus + K;
+          FT_Vector*  vec1 = exc->zp0.orus + L;
+          FT_Vector*  vec2 = exc->zp1.orus + K;
 
 
-          if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+          if ( exc->metrics.x_scale == exc->metrics.y_scale )
           {
             /* this should be faster */
-            D = CUR_Func_dualproj( vec1, vec2 );
-            D = FT_MulFix( D, CUR.metrics.x_scale );
+            D = DUALPROJ( vec1, vec2 );
+            D = FT_MulFix( D, exc->metrics.x_scale );
           }
           else
           {
             FT_Vector  vec;
 
 
-            vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
-            vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
+            vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
+            vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
 
-            D = CUR_fast_dualproj( &vec );
+            D = FAST_DUALPROJ( &vec );
           }
         }
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
-    if ( SUBPIXEL_HINTING                       &&
-         CUR.ignore_x_mode && FT_ABS( D ) == 64 )
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         exc->ignore_x_mode          &&
+         FT_ABS( D ) == 64           )
       D += 1;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = D;
   }
@@ -5448,61 +4836,63 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* SDPVTL[a]:    Set Dual PVector to Line                                */
+  /* SDPvTL[a]:    Set Dual PVector to Line                                */
   /* Opcode range: 0x86-0x87                                               */
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_SDPVTL( INS_ARG )
+  Ins_SDPVTL( TT_ExecContext  exc,
+              FT_Long*        args )
   {
     FT_Long    A, B, C;
     FT_UShort  p1, p2;            /* was FT_Int in pas type ERROR */
-    FT_Int     aOpc = CUR.opcode;
+
+    FT_Byte  opcode = exc->opcode;
 
 
     p1 = (FT_UShort)args[1];
     p2 = (FT_UShort)args[0];
 
-    if ( BOUNDS( p2, CUR.zp1.n_points ) ||
-         BOUNDS( p1, CUR.zp2.n_points ) )
+    if ( BOUNDS( p2, exc->zp1.n_points ) ||
+         BOUNDS( p1, exc->zp2.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     {
-      FT_Vector* v1 = CUR.zp1.org + p2;
-      FT_Vector* v2 = CUR.zp2.org + p1;
+      FT_Vector* v1 = exc->zp1.org + p2;
+      FT_Vector* v2 = exc->zp2.org + p1;
 
 
       A = v1->x - v2->x;
       B = v1->y - v2->y;
 
-      /* If v1 == v2, SDPVTL behaves the same as */
+      /* If v1 == v2, SDPvTL behaves the same as */
       /* SVTCA[X], respectively.                 */
       /*                                         */
       /* Confirmed by Greg Hitchcock.            */
 
       if ( A == 0 && B == 0 )
       {
-        A    = 0x4000;
-        aOpc = 0;
+        A      = 0x4000;
+        opcode = 0;
       }
     }
 
-    if ( ( aOpc & 1 ) != 0 )
+    if ( ( opcode & 1 ) != 0 )
     {
       C =  B;   /* counter clockwise rotation */
       B =  A;
       A = -C;
     }
 
-    NORMalize( A, B, &CUR.GS.dualVector );
+    Normalize( A, B, &exc->GS.dualVector );
 
     {
-      FT_Vector*  v1 = CUR.zp1.cur + p2;
-      FT_Vector*  v2 = CUR.zp2.cur + p1;
+      FT_Vector*  v1 = exc->zp1.cur + p2;
+      FT_Vector*  v2 = exc->zp2.cur + p1;
 
 
       A = v1->x - v2->x;
@@ -5510,23 +4900,20 @@
 
       if ( A == 0 && B == 0 )
       {
-        A    = 0x4000;
-        aOpc = 0;
+        A      = 0x4000;
+        opcode = 0;
       }
     }
 
-    if ( ( aOpc & 1 ) != 0 )
+    if ( ( opcode & 1 ) != 0 )
     {
       C =  B;   /* counter clockwise rotation */
       B =  A;
       A = -C;
     }
 
-    NORMalize( A, B, &CUR.GS.projVector );
-
-    GUESS_VECTOR( freeVector );
-
-    COMPUTE_Funcs();
+    Normalize( A, B, &exc->GS.projVector );
+    Compute_Funcs( exc );
   }
 
 
@@ -5537,25 +4924,26 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_SZP0( INS_ARG )
+  Ins_SZP0( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     switch ( (FT_Int)args[0] )
     {
     case 0:
-      CUR.zp0 = CUR.twilight;
+      exc->zp0 = exc->twilight;
       break;
 
     case 1:
-      CUR.zp0 = CUR.pts;
+      exc->zp0 = exc->pts;
       break;
 
     default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    CUR.GS.gep0 = (FT_UShort)args[0];
+    exc->GS.gep0 = (FT_UShort)args[0];
   }
 
 
@@ -5566,25 +4954,26 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_SZP1( INS_ARG )
+  Ins_SZP1( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     switch ( (FT_Int)args[0] )
     {
     case 0:
-      CUR.zp1 = CUR.twilight;
+      exc->zp1 = exc->twilight;
       break;
 
     case 1:
-      CUR.zp1 = CUR.pts;
+      exc->zp1 = exc->pts;
       break;
 
     default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    CUR.GS.gep1 = (FT_UShort)args[0];
+    exc->GS.gep1 = (FT_UShort)args[0];
   }
 
 
@@ -5595,25 +4984,26 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_SZP2( INS_ARG )
+  Ins_SZP2( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     switch ( (FT_Int)args[0] )
     {
     case 0:
-      CUR.zp2 = CUR.twilight;
+      exc->zp2 = exc->twilight;
       break;
 
     case 1:
-      CUR.zp2 = CUR.pts;
+      exc->zp2 = exc->pts;
       break;
 
     default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    CUR.GS.gep2 = (FT_UShort)args[0];
+    exc->GS.gep2 = (FT_UShort)args[0];
   }
 
 
@@ -5624,60 +5014,93 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_SZPS( INS_ARG )
+  Ins_SZPS( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     switch ( (FT_Int)args[0] )
     {
     case 0:
-      CUR.zp0 = CUR.twilight;
+      exc->zp0 = exc->twilight;
       break;
 
     case 1:
-      CUR.zp0 = CUR.pts;
+      exc->zp0 = exc->pts;
       break;
 
     default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    CUR.zp1 = CUR.zp0;
-    CUR.zp2 = CUR.zp0;
+    exc->zp1 = exc->zp0;
+    exc->zp2 = exc->zp0;
 
-    CUR.GS.gep0 = (FT_UShort)args[0];
-    CUR.GS.gep1 = (FT_UShort)args[0];
-    CUR.GS.gep2 = (FT_UShort)args[0];
+    exc->GS.gep0 = (FT_UShort)args[0];
+    exc->GS.gep1 = (FT_UShort)args[0];
+    exc->GS.gep2 = (FT_UShort)args[0];
   }
 
 
   /*************************************************************************/
   /*                                                                       */
   /* INSTCTRL[]:   INSTruction ConTRoL                                     */
-  /* Opcode range: 0x8e                                                    */
+  /* Opcode range: 0x8E                                                    */
   /* Stack:        int32 int32 -->                                         */
   /*                                                                       */
   static void
-  Ins_INSTCTRL( INS_ARG )
+  Ins_INSTCTRL( TT_ExecContext  exc,
+                FT_Long*        args )
   {
-    FT_Long  K, L;
+    FT_ULong  K, L, Kf;
 
 
-    K = args[1];
-    L = args[0];
+    K = (FT_ULong)args[1];
+    L = (FT_ULong)args[0];
 
-    if ( K < 1 || K > 2 )
+    /* selector values cannot be `OR'ed;                 */
+    /* they are indices starting with index 1, not flags */
+    if ( K < 1 || K > 3 )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    if ( L != 0 )
-        L = K;
+    /* convert index to flag value */
+    Kf = 1 << ( K - 1 );
 
-    CUR.GS.instruct_control = FT_BOOL(
-      ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
+    if ( L != 0 )
+    {
+      /* arguments to selectors look like flag values */
+      if ( L != Kf )
+      {
+        if ( exc->pedantic_hinting )
+          exc->error = FT_THROW( Invalid_Reference );
+        return;
+      }
+    }
+
+    exc->GS.instruct_control &= ~(FT_Byte)Kf;
+    exc->GS.instruct_control |= (FT_Byte)L;
+
+    if ( K == 3 )
+    {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      /* INSTCTRL modifying flag 3 also has an effect */
+      /* outside of the CVT program                   */
+      if ( SUBPIXEL_HINTING_INFINALITY )
+        exc->ignore_x_mode = FT_BOOL( L == 4 );
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      /* Native ClearType fonts sign a waiver that turns off all backwards */
+      /* compatibility hacks and lets them program points to the grid like */
+      /* it's 1996.  They might sign a waiver for just one glyph, though.  */
+      if ( SUBPIXEL_HINTING_MINIMAL )
+        exc->backwards_compatibility = !FT_BOOL( L == 4 );
+#endif
+    }
   }
 
 
@@ -5688,7 +5111,8 @@
   /* Stack:        uint32? -->                                             */
   /*                                                                       */
   static void
-  Ins_SCANCTRL( INS_ARG )
+  Ins_SCANCTRL( TT_ExecContext  exc,
+                FT_Long*        args )
   {
     FT_Int  A;
 
@@ -5698,32 +5122,32 @@
 
     if ( A == 0xFF )
     {
-      CUR.GS.scan_control = TRUE;
+      exc->GS.scan_control = TRUE;
       return;
     }
     else if ( A == 0 )
     {
-      CUR.GS.scan_control = FALSE;
+      exc->GS.scan_control = FALSE;
       return;
     }
 
-    if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
-      CUR.GS.scan_control = TRUE;
+    if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A )
+      exc->GS.scan_control = TRUE;
 
-    if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
-      CUR.GS.scan_control = TRUE;
+    if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated )
+      exc->GS.scan_control = TRUE;
 
-    if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
-      CUR.GS.scan_control = TRUE;
+    if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched )
+      exc->GS.scan_control = TRUE;
 
-    if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
-      CUR.GS.scan_control = FALSE;
+    if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A )
+      exc->GS.scan_control = FALSE;
 
-    if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
-      CUR.GS.scan_control = FALSE;
+    if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated )
+      exc->GS.scan_control = FALSE;
 
-    if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
-      CUR.GS.scan_control = FALSE;
+    if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched )
+      exc->GS.scan_control = FALSE;
   }
 
 
@@ -5734,10 +5158,11 @@
   /* Stack:        uint32? -->                                             */
   /*                                                                       */
   static void
-  Ins_SCANTYPE( INS_ARG )
+  Ins_SCANTYPE( TT_ExecContext  exc,
+                FT_Long*        args )
   {
     if ( args[0] >= 0 )
-      CUR.GS.scan_type = (FT_Int)args[0];
+      exc->GS.scan_type = (FT_Int)args[0];
   }
 
 
@@ -5745,8 +5170,6 @@
   /*                                                                       */
   /* MANAGING OUTLINES                                                     */
   /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
   /*************************************************************************/
 
 
@@ -5757,43 +5180,50 @@
   /* Stack:        uint32... -->                                           */
   /*                                                                       */
   static void
-  Ins_FLIPPT( INS_ARG )
+  Ins_FLIPPT( TT_ExecContext  exc )
   {
     FT_UShort  point;
 
-    FT_UNUSED_ARG;
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      goto Fail;
+#endif
 
-    if ( CUR.top < CUR.GS.loop )
+    if ( exc->top < exc->GS.loop )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Too_Few_Arguments );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Too_Few_Arguments );
       goto Fail;
     }
 
-    while ( CUR.GS.loop > 0 )
+    while ( exc->GS.loop > 0 )
     {
-      CUR.args--;
+      exc->args--;
 
-      point = (FT_UShort)CUR.stack[CUR.args];
+      point = (FT_UShort)exc->stack[exc->args];
 
-      if ( BOUNDS( point, CUR.pts.n_points ) )
+      if ( BOUNDS( point, exc->pts.n_points ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
-        CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
+        exc->pts.tags[point] ^= FT_CURVE_TAG_ON;
 
-      CUR.GS.loop--;
+      exc->GS.loop--;
     }
 
   Fail:
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
+    exc->GS.loop = 1;
+    exc->new_top = exc->args;
   }
 
 
@@ -5804,24 +5234,34 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_FLIPRGON( INS_ARG )
+  Ins_FLIPRGON( TT_ExecContext  exc,
+                FT_Long*        args )
   {
     FT_UShort  I, K, L;
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+#endif
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
-    if ( BOUNDS( K, CUR.pts.n_points ) ||
-         BOUNDS( L, CUR.pts.n_points ) )
+    if ( BOUNDS( K, exc->pts.n_points ) ||
+         BOUNDS( L, exc->pts.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     for ( I = L; I <= K; I++ )
-      CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
+      exc->pts.tags[I] |= FT_CURVE_TAG_ON;
   }
 
 
@@ -5832,53 +5272,64 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_FLIPRGOFF( INS_ARG )
+  Ins_FLIPRGOFF( TT_ExecContext  exc,
+                 FT_Long*        args )
   {
     FT_UShort  I, K, L;
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+#endif
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
-    if ( BOUNDS( K, CUR.pts.n_points ) ||
-         BOUNDS( L, CUR.pts.n_points ) )
+    if ( BOUNDS( K, exc->pts.n_points ) ||
+         BOUNDS( L, exc->pts.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     for ( I = L; I <= K; I++ )
-      CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
+      exc->pts.tags[I] &= ~FT_CURVE_TAG_ON;
   }
 
 
   static FT_Bool
-  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,
-                                       FT_F26Dot6*   y,
-                                       TT_GlyphZone  zone,
-                                       FT_UShort*    refp )
+  Compute_Point_Displacement( TT_ExecContext  exc,
+                              FT_F26Dot6*     x,
+                              FT_F26Dot6*     y,
+                              TT_GlyphZone    zone,
+                              FT_UShort*      refp )
   {
     TT_GlyphZoneRec  zp;
     FT_UShort        p;
     FT_F26Dot6       d;
 
 
-    if ( CUR.opcode & 1 )
+    if ( exc->opcode & 1 )
     {
-      zp = CUR.zp0;
-      p  = CUR.GS.rp1;
+      zp = exc->zp0;
+      p  = exc->GS.rp1;
     }
     else
     {
-      zp = CUR.zp1;
-      p  = CUR.GS.rp2;
+      zp = exc->zp1;
+      p  = exc->GS.rp2;
     }
 
     if ( BOUNDS( p, zp.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       *refp = 0;
       return FAILURE;
     }
@@ -5886,70 +5337,47 @@
     *zone = zp;
     *refp = p;
 
-    d = CUR_Func_project( zp.cur + p, zp.org + p );
+    d = PROJECT( zp.cur + p, zp.org + p );
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      if ( CUR.GS.both_x_axis )
-      {
-        *x = d;
-        *y = 0;
-      }
-      else
-      {
-        *x = 0;
-        *y = d;
-      }
-    }
-    else
-#endif
-    {
-      *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P );
-      *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P );
-    }
+    *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P );
+    *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P );
 
     return SUCCESS;
   }
 
 
+  /* See `ttinterp.h' for details on backwards compatibility mode. */
   static void
-  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
-                           FT_F26Dot6  dx,
-                           FT_F26Dot6  dy,
-                           FT_Bool     touch )
+  Move_Zp2_Point( TT_ExecContext  exc,
+                  FT_UShort       point,
+                  FT_F26Dot6      dx,
+                  FT_F26Dot6      dy,
+                  FT_Bool         touch )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
+    if ( exc->GS.freeVector.x != 0 )
     {
-      if ( CUR.GS.both_x_axis )
-      {
-        CUR.zp2.cur[point].x += dx;
-        if ( touch )
-          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
-      }
-      else
-      {
-        CUR.zp2.cur[point].y += dy;
-        if ( touch )
-          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
-      }
-      return;
-    }
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility ) )
 #endif
+        exc->zp2.cur[point].x += dx;
 
-    if ( CUR.GS.freeVector.x != 0 )
-    {
-      CUR.zp2.cur[point].x += dx;
       if ( touch )
-        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+        exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
 
-    if ( CUR.GS.freeVector.y != 0 )
+    if ( exc->GS.freeVector.y != 0 )
     {
-      CUR.zp2.cur[point].y += dy;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+#endif
+        exc->zp2.cur[point].y += dy;
+
       if ( touch )
-        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+        exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
   }
 
@@ -5961,57 +5389,53 @@
   /* Stack:        uint32... -->                                           */
   /*                                                                       */
   static void
-  Ins_SHP( INS_ARG )
+  Ins_SHP( TT_ExecContext  exc )
   {
     TT_GlyphZoneRec  zp;
     FT_UShort        refp;
 
-    FT_F26Dot6       dx,
-                     dy;
+    FT_F26Dot6       dx, dy;
     FT_UShort        point;
 
-    FT_UNUSED_ARG;
 
-
-    if ( CUR.top < CUR.GS.loop )
+    if ( exc->top < exc->GS.loop )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+    if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
       return;
 
-    while ( CUR.GS.loop > 0 )
+    while ( exc->GS.loop > 0 )
     {
-      CUR.args--;
-      point = (FT_UShort)CUR.stack[CUR.args];
+      exc->args--;
+      point = (FT_UShort)exc->stack[exc->args];
 
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      if ( BOUNDS( point, exc->zp2.n_points ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* doesn't follow Cleartype spec but produces better result */
-      if ( SUBPIXEL_HINTING  &&
-           CUR.ignore_x_mode )
-        MOVE_Zp2_Point( point, 0, dy, TRUE );
+      if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode )
+        Move_Zp2_Point( exc, point, 0, dy, TRUE );
       else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        MOVE_Zp2_Point( point, dx, dy, TRUE );
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+        Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
-      CUR.GS.loop--;
+      exc->GS.loop--;
     }
 
   Fail:
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
+    exc->GS.loop = 1;
+    exc->new_top = exc->args;
   }
 
 
@@ -6026,7 +5450,8 @@
   /*               zero which includes all points of it.                   */
   /*                                                                       */
   static void
-  Ins_SHC( INS_ARG )
+  Ins_SHC( TT_ExecContext  exc,
+           FT_Long*        args )
   {
     TT_GlyphZoneRec  zp;
     FT_UShort        refp;
@@ -6036,36 +5461,36 @@
     FT_UShort        start, limit, i;
 
 
-    contour = (FT_UShort)args[0];
-    bounds  = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours;
+    contour = (FT_Short)args[0];
+    bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
 
     if ( BOUNDS( contour, bounds ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+    if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
       return;
 
     if ( contour == 0 )
       start = 0;
     else
-      start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 -
-                           CUR.zp2.first_point );
+      start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
+                           exc->zp2.first_point );
 
     /* we use the number of points if in the twilight zone */
-    if ( CUR.GS.gep2 == 0 )
-      limit = CUR.zp2.n_points;
+    if ( exc->GS.gep2 == 0 )
+      limit = exc->zp2.n_points;
     else
-      limit = (FT_UShort)( CUR.zp2.contours[contour] -
-                           CUR.zp2.first_point + 1 );
+      limit = (FT_UShort)( exc->zp2.contours[contour] -
+                           exc->zp2.first_point + 1 );
 
     for ( i = start; i < limit; i++ )
     {
-      if ( zp.cur != CUR.zp2.cur || refp != i )
-        MOVE_Zp2_Point( i, dx, dy, TRUE );
+      if ( zp.cur != exc->zp2.cur || refp != i )
+        Move_Zp2_Point( exc, i, dx, dy, TRUE );
     }
   }
 
@@ -6077,7 +5502,8 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_SHZ( INS_ARG )
+  Ins_SHZ( TT_ExecContext  exc,
+           FT_Long*        args )
   {
     TT_GlyphZoneRec  zp;
     FT_UShort        refp;
@@ -6089,30 +5515,30 @@
 
     if ( BOUNDS( args[0], 2 ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+    if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
       return;
 
     /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.     */
     /*      Twilight zone has no real contours, so use `n_points'. */
     /*      Normal zone's `n_points' includes phantoms, so must    */
     /*      use end of last contour.                               */
-    if ( CUR.GS.gep2 == 0 )
-      limit = (FT_UShort)CUR.zp2.n_points;
-    else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
-      limit = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] + 1 );
+    if ( exc->GS.gep2 == 0 )
+      limit = (FT_UShort)exc->zp2.n_points;
+    else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
+      limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
     else
       limit = 0;
 
     /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
     for ( i = 0; i < limit; i++ )
     {
-      if ( zp.cur != CUR.zp2.cur || refp != i )
-        MOVE_Zp2_Point( i, dx, dy, FALSE );
+      if ( zp.cur != exc->zp2.cur || refp != i )
+        Move_Zp2_Point( exc, i, dx, dy, FALSE );
     }
   }
 
@@ -6124,148 +5550,152 @@
   /* Stack:        f26.6 uint32... -->                                     */
   /*                                                                       */
   static void
-  Ins_SHPIX( INS_ARG )
+  Ins_SHPIX( TT_ExecContext  exc,
+             FT_Long*        args )
   {
     FT_F26Dot6  dx, dy;
     FT_UShort   point;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Int      B1, B2;
 #endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    FT_Bool     in_twilight = exc->GS.gep0 == 0 || \
+                              exc->GS.gep1 == 0 || \
+                              exc->GS.gep2 == 0;
+#endif
 
 
-    if ( CUR.top < CUR.GS.loop + 1 )
+
+    if ( exc->top < exc->GS.loop + 1 )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      if ( CUR.GS.both_x_axis )
-      {
-        dx = (FT_UInt32)args[0];
-        dy = 0;
-      }
-      else
-      {
-        dx = 0;
-        dy = (FT_UInt32)args[0];
-      }
-    }
-    else
-#endif
-    {
-      dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
-      dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
-    }
+    dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
+    dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
 
-    while ( CUR.GS.loop > 0 )
+    while ( exc->GS.loop > 0 )
     {
-      CUR.args--;
+      exc->args--;
 
-      point = (FT_UShort)CUR.stack[CUR.args];
+      point = (FT_UShort)exc->stack[exc->args];
 
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      if ( BOUNDS( point, exc->zp2.n_points ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
-        /*  If not using ignore_x_mode rendering, allow ZP2 move.          */
-        /*  If inline deltas aren't allowed, skip ZP2 move.                */
-        /*  If using ignore_x_mode rendering, allow ZP2 point move if:     */
-        /*   - freedom vector is y and sph_compatibility_mode is off       */
-        /*   - the glyph is composite and the move is in the Y direction   */
-        /*   - the glyph is specifically set to allow SHPIX moves          */
-        /*   - the move is on a previously Y-touched point                 */
+        /*  If not using ignore_x_mode rendering, allow ZP2 move.        */
+        /*  If inline deltas aren't allowed, skip ZP2 move.              */
+        /*  If using ignore_x_mode rendering, allow ZP2 point move if:   */
+        /*   - freedom vector is y and sph_compatibility_mode is off     */
+        /*   - the glyph is composite and the move is in the Y direction */
+        /*   - the glyph is specifically set to allow SHPIX moves        */
+        /*   - the move is on a previously Y-touched point               */
 
-        if ( SUBPIXEL_HINTING  &&
-             CUR.ignore_x_mode )
+        if ( exc->ignore_x_mode )
         {
           /* save point for later comparison */
-          if ( CUR.GS.freeVector.y != 0 )
-            B1 = CUR.zp2.cur[point].y;
+          if ( exc->GS.freeVector.y != 0 )
+            B1 = exc->zp2.cur[point].y;
           else
-            B1 = CUR.zp2.cur[point].x;
+            B1 = exc->zp2.cur[point].x;
 
-          if ( !CUR.face->sph_compatibility_mode &&
-               CUR.GS.freeVector.y != 0          )
+          if ( !exc->face->sph_compatibility_mode &&
+               exc->GS.freeVector.y != 0          )
           {
-            MOVE_Zp2_Point( point, dx, dy, TRUE );
+            Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
             /* save new point */
-            if ( CUR.GS.freeVector.y != 0 )
+            if ( exc->GS.freeVector.y != 0 )
             {
-              B2 = CUR.zp2.cur[point].y;
+              B2 = exc->zp2.cur[point].y;
 
               /* reverse any disallowed moves */
-              if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
-                   ( B1 & 63 ) != 0                                          &&
-                   ( B2 & 63 ) != 0                                          &&
-                    B1 != B2                                                 )
-                MOVE_Zp2_Point( point, -dx, -dy, TRUE );
+              if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+                   ( B1 & 63 ) != 0                                           &&
+                   ( B2 & 63 ) != 0                                           &&
+                   B1 != B2                                                   )
+                Move_Zp2_Point( exc, point, -dx, -dy, TRUE );
             }
           }
-          else if ( CUR.face->sph_compatibility_mode )
+          else if ( exc->face->sph_compatibility_mode )
           {
-            if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+            if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
             {
               dx = FT_PIX_ROUND( B1 + dx ) - B1;
               dy = FT_PIX_ROUND( B1 + dy ) - B1;
             }
 
             /* skip post-iup deltas */
-            if ( CUR.iup_called                                          &&
-                 ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
-                   ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
+            if ( exc->iup_called                                          &&
+                 ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
+                   ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
               goto Skip;
 
-            if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
-                  ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
-                    ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )   ||
-                    ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX )     )   )
-              MOVE_Zp2_Point( point, 0, dy, TRUE );
+            if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
+                  ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+                    ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )    ||
+                    ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX )      )  )
+              Move_Zp2_Point( exc, point, 0, dy, TRUE );
 
             /* save new point */
-            if ( CUR.GS.freeVector.y != 0 )
+            if ( exc->GS.freeVector.y != 0 )
             {
-              B2 = CUR.zp2.cur[point].y;
+              B2 = exc->zp2.cur[point].y;
 
               /* reverse any disallowed moves */
               if ( ( B1 & 63 ) == 0 &&
                    ( B2 & 63 ) != 0 &&
                    B1 != B2         )
-                MOVE_Zp2_Point( point, 0, -dy, TRUE );
+                Move_Zp2_Point( exc, point, 0, -dy, TRUE );
             }
           }
-          else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
-            MOVE_Zp2_Point( point, dx, dy, TRUE );
+          else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
+            Move_Zp2_Point( exc, point, dx, dy, TRUE );
         }
         else
-          MOVE_Zp2_Point( point, dx, dy, TRUE );
+          Move_Zp2_Point( exc, point, dx, dy, TRUE );
       }
+      else
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( SUBPIXEL_HINTING_MINIMAL     &&
+           exc->backwards_compatibility )
+      {
+        /* Special case: allow SHPIX to move points in the twilight zone.  */
+        /* Otherwise, treat SHPIX the same as DELTAP.  Unbreaks various    */
+        /* fonts such as older versions of Rokkitt and DTL Argo T Light    */
+        /* that would glitch severly after calling ALIGNRP after a blocked */
+        /* SHPIX.                                                          */
+        if ( in_twilight                                                ||
+             ( !( exc->iupx_called && exc->iupy_called )              &&
+               ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+                 ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )    ) ) )
+          Move_Zp2_Point( exc, point, 0, dy, TRUE );
+      }
+      else
+#endif
+        Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     Skip:
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-        MOVE_Zp2_Point( point, dx, dy, TRUE );
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-      CUR.GS.loop--;
+#endif
+      exc->GS.loop--;
     }
 
   Fail:
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
+    exc->GS.loop = 1;
+    exc->new_top = exc->args;
   }
 
 
@@ -6276,65 +5706,63 @@
   /* Stack:        f26.6 uint32 -->                                        */
   /*                                                                       */
   static void
-  Ins_MSIRP( INS_ARG )
+  Ins_MSIRP( TT_ExecContext  exc,
+             FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  distance;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    FT_F26Dot6  control_value_cutin = 0; /* pacify compiler */
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    FT_F26Dot6  control_value_cutin = 0;
 
 
-    if ( SUBPIXEL_HINTING )
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
-      control_value_cutin = CUR.GS.control_value_cutin;
+      control_value_cutin = exc->GS.control_value_cutin;
 
-      if ( CUR.ignore_x_mode                                 &&
-           CUR.GS.freeVector.x != 0                          &&
-           !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+      if ( exc->ignore_x_mode                                 &&
+           exc->GS.freeVector.x != 0                          &&
+           !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
         control_value_cutin = 0;
     }
-
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    if ( BOUNDS( point,       exc->zp1.n_points ) ||
+         BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     /* UNDOCUMENTED!  The MS rasterizer does that with */
     /* twilight points (confirmed by Greg Hitchcock)   */
-    if ( CUR.GS.gep1 == 0 )
+    if ( exc->GS.gep1 == 0 )
     {
-      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
-      CUR_Func_move_orig( &CUR.zp1, point, args[1] );
-      CUR.zp1.cur[point] = CUR.zp1.org[point];
+      exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0];
+      exc->func_move_orig( exc, &exc->zp1, point, args[1] );
+      exc->zp1.cur[point] = exc->zp1.org[point];
     }
 
-    distance = CUR_Func_project( CUR.zp1.cur + point,
-                                 CUR.zp0.cur + CUR.GS.rp0 );
+    distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* subpixel hinting - make MSIRP respect CVT cut-in; */
-    if ( SUBPIXEL_HINTING                                    &&
-         CUR.ignore_x_mode                                   &&
-         CUR.GS.freeVector.x != 0                            &&
+    if ( SUBPIXEL_HINTING_INFINALITY                         &&
+         exc->ignore_x_mode                                  &&
+         exc->GS.freeVector.x != 0                           &&
          FT_ABS( distance - args[1] ) >= control_value_cutin )
       distance = args[1];
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+    exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
-    CUR.GS.rp1 = CUR.GS.rp0;
-    CUR.GS.rp2 = point;
+    exc->GS.rp1 = exc->GS.rp0;
+    exc->GS.rp2 = point;
 
-    if ( ( CUR.opcode & 1 ) != 0 )
-      CUR.GS.rp0 = point;
+    if ( ( exc->opcode & 1 ) != 0 )
+      exc->GS.rp0 = point;
   }
 
 
@@ -6345,7 +5773,8 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_MDAP( INS_ARG )
+  Ins_MDAP( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_UShort   point;
     FT_F26Dot6  cur_dist;
@@ -6354,36 +5783,38 @@
 
     point = (FT_UShort)args[0];
 
-    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    if ( BOUNDS( point, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    if ( ( CUR.opcode & 1 ) != 0 )
+    if ( ( exc->opcode & 1 ) != 0 )
     {
-      cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING         &&
-           CUR.ignore_x_mode        &&
-           CUR.GS.freeVector.x != 0 )
-        distance = ROUND_None(
+      cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
+        distance = Round_None(
+                     exc,
                      cur_dist,
-                     CUR.tt_metrics.compensations[0] ) - cur_dist;
+                     exc->tt_metrics.compensations[0] ) - cur_dist;
       else
 #endif
-        distance = CUR_Func_round(
+        distance = exc->func_round(
+                     exc,
                      cur_dist,
-                     CUR.tt_metrics.compensations[0] ) - cur_dist;
+                     exc->tt_metrics.compensations[0] ) - cur_dist;
     }
     else
       distance = 0;
 
-    CUR_Func_move( &CUR.zp0, point, distance );
+    exc->func_move( exc, &exc->zp0, point, distance );
 
-    CUR.GS.rp0 = point;
-    CUR.GS.rp1 = point;
+    exc->GS.rp0 = point;
+    exc->GS.rp1 = point;
   }
 
 
@@ -6394,7 +5825,8 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_MIAP( INS_ARG )
+  Ins_MIAP( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_ULong    cvtEntry;
     FT_UShort   point;
@@ -6403,24 +5835,24 @@
     FT_F26Dot6  control_value_cutin;
 
 
-    control_value_cutin = CUR.GS.control_value_cutin;
+    control_value_cutin = exc->GS.control_value_cutin;
     cvtEntry            = (FT_ULong)args[1];
     point               = (FT_UShort)args[0];
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                  &&
-         CUR.ignore_x_mode                                 &&
-         CUR.GS.freeVector.x != 0                          &&
-         CUR.GS.freeVector.y == 0                          &&
-         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
+         exc->ignore_x_mode                                 &&
+         exc->GS.freeVector.x != 0                          &&
+         exc->GS.freeVector.y == 0                          &&
+         !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       control_value_cutin = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    if ( BOUNDS( point,     CUR.zp0.n_points ) ||
-         BOUNDSL( cvtEntry, CUR.cvtSize )      )
+    if ( BOUNDS( point,     exc->zp0.n_points ) ||
+         BOUNDSL( cvtEntry, exc->cvtSize )      )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6444,56 +5876,58 @@
     /*                                                                    */
     /* Confirmed by Greg Hitchcock.                                       */
 
-    distance = CUR_Func_read_cvt( cvtEntry );
+    distance = exc->func_read_cvt( exc, cvtEntry );
 
-    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
+    if ( exc->GS.gep0 == 0 )   /* If in twilight zone */
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
       /* Determined via experimentation and may be incorrect...         */
-      if ( !SUBPIXEL_HINTING                     ||
-           ( !CUR.ignore_x_mode                ||
-             !CUR.face->sph_compatibility_mode ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
-                                            CUR.GS.freeVector.x );
-      CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
-                                          CUR.GS.freeVector.y ),
-      CUR.zp0.cur[point]   = CUR.zp0.org[point];
+      if ( !( SUBPIXEL_HINTING_INFINALITY           &&
+              ( exc->ignore_x_mode                &&
+                exc->face->sph_compatibility_mode ) ) )
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+        exc->zp0.org[point].x = TT_MulFix14( distance,
+                                             exc->GS.freeVector.x );
+      exc->zp0.org[point].y = TT_MulFix14( distance,
+                                           exc->GS.freeVector.y ),
+      exc->zp0.cur[point]   = exc->zp0.org[point];
     }
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                              &&
-         CUR.ignore_x_mode                             &&
-         ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
-         distance > 0                                  &&
-         CUR.GS.freeVector.y != 0                      )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                    &&
+         exc->ignore_x_mode                             &&
+         ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
+         distance > 0                                   &&
+         exc->GS.freeVector.y != 0                      )
       distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
+    org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
 
-    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cut-in flag */
+    if ( ( exc->opcode & 1 ) != 0 )   /* rounding and control cut-in flag */
     {
       if ( FT_ABS( distance - org_dist ) > control_value_cutin )
         distance = org_dist;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING         &&
-           CUR.ignore_x_mode        &&
-           CUR.GS.freeVector.x != 0 )
-        distance = ROUND_None( distance,
-                               CUR.tt_metrics.compensations[0] );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
+        distance = Round_None( exc,
+                               distance,
+                               exc->tt_metrics.compensations[0] );
       else
 #endif
-        distance = CUR_Func_round( distance,
-                                   CUR.tt_metrics.compensations[0] );
+        distance = exc->func_round( exc,
+                                    distance,
+                                    exc->tt_metrics.compensations[0] );
     }
 
-    CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+    exc->func_move( exc, &exc->zp0, point, distance - org_dist );
 
   Fail:
-    CUR.GS.rp0 = point;
-    CUR.GS.rp1 = point;
+    exc->GS.rp0 = point;
+    exc->GS.rp1 = point;
   }
 
 
@@ -6504,29 +5938,30 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_MDRP( INS_ARG )
+  Ins_MDRP( TT_ExecContext  exc,
+            FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  org_dist, distance, minimum_distance;
 
 
-    minimum_distance = CUR.GS.minimum_distance;
+    minimum_distance = exc->GS.minimum_distance;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                  &&
-         CUR.ignore_x_mode                                 &&
-         CUR.GS.freeVector.x != 0                          &&
-         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
+         exc->ignore_x_mode                                 &&
+         exc->GS.freeVector.x != 0                          &&
+         !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       minimum_distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    if ( BOUNDS( point,       exc->zp1.n_points ) ||
+         BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6535,74 +5970,77 @@
 
     /* XXX: UNDOCUMENTED: twilight zone special case */
 
-    if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
+    if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
     {
-      FT_Vector*  vec1 = &CUR.zp1.org[point];
-      FT_Vector*  vec2 = &CUR.zp0.org[CUR.GS.rp0];
+      FT_Vector*  vec1 = &exc->zp1.org[point];
+      FT_Vector*  vec2 = &exc->zp0.org[exc->GS.rp0];
 
 
-      org_dist = CUR_Func_dualproj( vec1, vec2 );
+      org_dist = DUALPROJ( vec1, vec2 );
     }
     else
     {
-      FT_Vector*  vec1 = &CUR.zp1.orus[point];
-      FT_Vector*  vec2 = &CUR.zp0.orus[CUR.GS.rp0];
+      FT_Vector*  vec1 = &exc->zp1.orus[point];
+      FT_Vector*  vec2 = &exc->zp0.orus[exc->GS.rp0];
 
 
-      if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+      if ( exc->metrics.x_scale == exc->metrics.y_scale )
       {
         /* this should be faster */
-        org_dist = CUR_Func_dualproj( vec1, vec2 );
-        org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale );
+        org_dist = DUALPROJ( vec1, vec2 );
+        org_dist = FT_MulFix( org_dist, exc->metrics.x_scale );
       }
       else
       {
         FT_Vector  vec;
 
 
-        vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
-        vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
+        vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
+        vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
 
-        org_dist = CUR_fast_dualproj( &vec );
+        org_dist = FAST_DUALPROJ( &vec );
       }
     }
 
     /* single width cut-in test */
 
-    if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
-         CUR.GS.single_width_cutin )
+    if ( FT_ABS( org_dist - exc->GS.single_width_value ) <
+         exc->GS.single_width_cutin )
     {
       if ( org_dist >= 0 )
-        org_dist = CUR.GS.single_width_value;
+        org_dist = exc->GS.single_width_value;
       else
-        org_dist = -CUR.GS.single_width_value;
+        org_dist = -exc->GS.single_width_value;
     }
 
     /* round flag */
 
-    if ( ( CUR.opcode & 4 ) != 0 )
+    if ( ( exc->opcode & 4 ) != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING         &&
-           CUR.ignore_x_mode        &&
-           CUR.GS.freeVector.x != 0 )
-        distance = ROUND_None(
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
+        distance = Round_None(
+                     exc,
                      org_dist,
-                     CUR.tt_metrics.compensations[CUR.opcode & 3] );
+                     exc->tt_metrics.compensations[exc->opcode & 3] );
       else
 #endif
-      distance = CUR_Func_round(
-                   org_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+        distance = exc->func_round(
+                     exc,
+                     org_dist,
+                     exc->tt_metrics.compensations[exc->opcode & 3] );
     }
     else
-      distance = ROUND_None(
+      distance = Round_None(
+                   exc,
                    org_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+                   exc->tt_metrics.compensations[exc->opcode & 3] );
 
     /* minimum distance flag */
 
-    if ( ( CUR.opcode & 8 ) != 0 )
+    if ( ( exc->opcode & 8 ) != 0 )
     {
       if ( org_dist >= 0 )
       {
@@ -6618,17 +6056,16 @@
 
     /* now move the point */
 
-    org_dist = CUR_Func_project( CUR.zp1.cur + point,
-                                 CUR.zp0.cur + CUR.GS.rp0 );
+    org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
 
-    CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+    exc->func_move( exc, &exc->zp1, point, distance - org_dist );
 
   Fail:
-    CUR.GS.rp1 = CUR.GS.rp0;
-    CUR.GS.rp2 = point;
+    exc->GS.rp1 = exc->GS.rp0;
+    exc->GS.rp2 = point;
 
-    if ( ( CUR.opcode & 16 ) != 0 )
-      CUR.GS.rp0 = point;
+    if ( ( exc->opcode & 16 ) != 0 )
+      exc->GS.rp0 = point;
   }
 
 
@@ -6639,7 +6076,8 @@
   /* Stack:        int32? uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_MIRP( INS_ARG )
+  Ins_MIRP( TT_ExecContext  exc,
+            FT_Long*        args )
   {
     FT_UShort   point;
     FT_ULong    cvtEntry;
@@ -6650,100 +6088,98 @@
                 org_dist,
                 control_value_cutin,
                 minimum_distance;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Int      B1           = 0; /* pacify compiler */
     FT_Int      B2           = 0;
     FT_Bool     reverse_move = FALSE;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
-    minimum_distance    = CUR.GS.minimum_distance;
-    control_value_cutin = CUR.GS.control_value_cutin;
+    minimum_distance    = exc->GS.minimum_distance;
+    control_value_cutin = exc->GS.control_value_cutin;
     point               = (FT_UShort)args[0];
     cvtEntry            = (FT_ULong)( args[1] + 1 );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                  &&
-         CUR.ignore_x_mode                                 &&
-         CUR.GS.freeVector.x != 0                          &&
-         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
+         exc->ignore_x_mode                                 &&
+         exc->GS.freeVector.x != 0                          &&
+         !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       control_value_cutin = minimum_distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDSL( cvtEntry,  CUR.cvtSize + 1 )  ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    if ( BOUNDS( point,       exc->zp1.n_points ) ||
+         BOUNDSL( cvtEntry,   exc->cvtSize + 1 )  ||
+         BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
     if ( !cvtEntry )
       cvt_dist = 0;
     else
-      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+      cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 );
 
     /* single width test */
 
-    if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
-         CUR.GS.single_width_cutin )
+    if ( FT_ABS( cvt_dist - exc->GS.single_width_value ) <
+         exc->GS.single_width_cutin )
     {
       if ( cvt_dist >= 0 )
-        cvt_dist =  CUR.GS.single_width_value;
+        cvt_dist =  exc->GS.single_width_value;
       else
-        cvt_dist = -CUR.GS.single_width_value;
+        cvt_dist = -exc->GS.single_width_value;
     }
 
     /* UNDOCUMENTED!  The MS rasterizer does that with */
     /* twilight points (confirmed by Greg Hitchcock)   */
-    if ( CUR.GS.gep1 == 0 )
+    if ( exc->GS.gep1 == 0 )
     {
-      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
-                             TT_MulFix14( (FT_UInt32)cvt_dist,
-                                          CUR.GS.freeVector.x );
-      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
-                             TT_MulFix14( (FT_UInt32)cvt_dist,
-                                          CUR.GS.freeVector.y );
-      CUR.zp1.cur[point]   = CUR.zp1.org[point];
+      exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x +
+                              TT_MulFix14( cvt_dist,
+                                           exc->GS.freeVector.x );
+      exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y +
+                              TT_MulFix14( cvt_dist,
+                                           exc->GS.freeVector.y );
+      exc->zp1.cur[point]   = exc->zp1.org[point];
     }
 
-    org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
-                                  &CUR.zp0.org[CUR.GS.rp0] );
-    cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
-                                  &CUR.zp0.cur[CUR.GS.rp0] );
+    org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] );
+    cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] );
 
     /* auto-flip test */
 
-    if ( CUR.GS.auto_flip )
+    if ( exc->GS.auto_flip )
     {
       if ( ( org_dist ^ cvt_dist ) < 0 )
         cvt_dist = -cvt_dist;
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                         &&
-         CUR.ignore_x_mode                                        &&
-         CUR.GS.freeVector.y != 0                                 &&
-         ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                               &&
+         exc->ignore_x_mode                                        &&
+         exc->GS.freeVector.y != 0                                 &&
+         ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
     {
       if ( cur_dist < -64 )
         cvt_dist -= 16;
       else if ( cur_dist > 64 && cur_dist < 84 )
         cvt_dist += 32;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* control value cut-in and round */
 
-    if ( ( CUR.opcode & 4 ) != 0 )
+    if ( ( exc->opcode & 4 ) != 0 )
     {
       /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
       /*      refer to the same zone.                                  */
 
-      if ( CUR.GS.gep0 == CUR.GS.gep1 )
+      if ( exc->GS.gep0 == exc->GS.gep1 )
       {
         /* XXX: According to Greg Hitchcock, the following wording is */
         /*      the right one:                                        */
@@ -6761,32 +6197,34 @@
           cvt_dist = org_dist;
       }
 
-      distance = CUR_Func_round(
+      distance = exc->func_round(
+                   exc,
                    cvt_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+                   exc->tt_metrics.compensations[exc->opcode & 3] );
     }
     else
     {
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* do cvt cut-in always in MIRP for sph */
-      if ( SUBPIXEL_HINTING           &&
-           CUR.ignore_x_mode          &&
-           CUR.GS.gep0 == CUR.GS.gep1 )
+      if ( SUBPIXEL_HINTING_INFINALITY  &&
+           exc->ignore_x_mode           &&
+           exc->GS.gep0 == exc->GS.gep1 )
       {
         if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
           cvt_dist = org_dist;
       }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-      distance = ROUND_None(
+      distance = Round_None(
+                   exc,
                    cvt_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+                   exc->tt_metrics.compensations[exc->opcode & 3] );
     }
 
     /* minimum distance test */
 
-    if ( ( CUR.opcode & 8 ) != 0 )
+    if ( ( exc->opcode & 8 ) != 0 )
     {
       if ( org_dist >= 0 )
       {
@@ -6800,62 +6238,62 @@
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
-      B1 = CUR.zp1.cur[point].y;
+      B1 = exc->zp1.cur[point].y;
 
       /* Round moves if necessary */
-      if ( CUR.ignore_x_mode                                          &&
-           CUR.GS.freeVector.y != 0                                   &&
-           ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
+      if ( exc->ignore_x_mode                                          &&
+           exc->GS.freeVector.y != 0                                   &&
+           ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
         distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
 
-      if ( CUR.ignore_x_mode                                      &&
-           CUR.GS.freeVector.y != 0                               &&
-           ( CUR.opcode & 16 ) == 0                               &&
-           ( CUR.opcode & 8 ) == 0                                &&
-           ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
+      if ( exc->ignore_x_mode                                      &&
+           exc->GS.freeVector.y != 0                               &&
+           ( exc->opcode & 16 ) == 0                               &&
+           ( exc->opcode & 8 ) == 0                                &&
+           ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
         distance += 64;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+    exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
-      B2 = CUR.zp1.cur[point].y;
+      B2 = exc->zp1.cur[point].y;
 
       /* Reverse move if necessary */
-      if ( CUR.ignore_x_mode )
+      if ( exc->ignore_x_mode )
       {
-        if ( CUR.face->sph_compatibility_mode                          &&
-             CUR.GS.freeVector.y != 0                                  &&
-             ( B1 & 63 ) == 0                                          &&
-             ( B2 & 63 ) != 0                                          )
+        if ( exc->face->sph_compatibility_mode &&
+             exc->GS.freeVector.y != 0         &&
+             ( B1 & 63 ) == 0                  &&
+             ( B2 & 63 ) != 0                  )
           reverse_move = TRUE;
 
-        if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
-             CUR.GS.freeVector.y != 0                                  &&
-             ( B2 & 63 ) != 0                                          &&
-             ( B1 & 63 ) != 0                                          )
+        if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+             exc->GS.freeVector.y != 0                                  &&
+             ( B2 & 63 ) != 0                                           &&
+             ( B1 & 63 ) != 0                                           )
           reverse_move = TRUE;
       }
 
       if ( reverse_move )
-        CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
+        exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   Fail:
-    CUR.GS.rp1 = CUR.GS.rp0;
+    exc->GS.rp1 = exc->GS.rp0;
 
-    if ( ( CUR.opcode & 16 ) != 0 )
-      CUR.GS.rp0 = point;
+    if ( ( exc->opcode & 16 ) != 0 )
+      exc->GS.rp0 = point;
 
-    CUR.GS.rp2 = point;
+    exc->GS.rp2 = point;
   }
 
 
@@ -6866,61 +6304,59 @@
   /* Stack:        uint32 uint32... -->                                    */
   /*                                                                       */
   static void
-  Ins_ALIGNRP( INS_ARG )
+  Ins_ALIGNRP( TT_ExecContext  exc )
   {
     FT_UShort   point;
     FT_F26Dot6  distance;
 
-    FT_UNUSED_ARG;
 
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                         &&
-         CUR.ignore_x_mode                                        &&
-         CUR.iup_called                                           &&
-         ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                               &&
+         exc->ignore_x_mode                                        &&
+         exc->iup_called                                           &&
+         ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
     {
-      CUR.error = FT_THROW( Invalid_Reference );
+      exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    if ( CUR.top < CUR.GS.loop ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    if ( exc->top < exc->GS.loop                  ||
+         BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
-    while ( CUR.GS.loop > 0 )
+    while ( exc->GS.loop > 0 )
     {
-      CUR.args--;
+      exc->args--;
 
-      point = (FT_UShort)CUR.stack[CUR.args];
+      point = (FT_UShort)exc->stack[exc->args];
 
-      if ( BOUNDS( point, CUR.zp1.n_points ) )
+      if ( BOUNDS( point, exc->zp1.n_points ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
       {
-        distance = CUR_Func_project( CUR.zp1.cur + point,
-                                     CUR.zp0.cur + CUR.GS.rp0 );
+        distance = PROJECT( exc->zp1.cur + point,
+                            exc->zp0.cur + exc->GS.rp0 );
 
-        CUR_Func_move( &CUR.zp1, point, -distance );
+        exc->func_move( exc, &exc->zp1, point, -distance );
       }
 
-      CUR.GS.loop--;
+      exc->GS.loop--;
     }
 
   Fail:
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
+    exc->GS.loop = 1;
+    exc->new_top = exc->args;
   }
 
 
@@ -6931,7 +6367,8 @@
   /* Stack:        5 * uint32 -->                                          */
   /*                                                                       */
   static void
-  Ins_ISECT( INS_ARG )
+  Ins_ISECT( TT_ExecContext  exc,
+             FT_Long*        args )
   {
     FT_UShort   point,
                 a0, a1,
@@ -6955,29 +6392,27 @@
     b0 = (FT_UShort)args[3];
     b1 = (FT_UShort)args[4];
 
-    if ( BOUNDS( b0, CUR.zp0.n_points )  ||
-         BOUNDS( b1, CUR.zp0.n_points )  ||
-         BOUNDS( a0, CUR.zp1.n_points )  ||
-         BOUNDS( a1, CUR.zp1.n_points )  ||
-         BOUNDS( point, CUR.zp2.n_points ) )
+    if ( BOUNDS( b0,    exc->zp0.n_points ) ||
+         BOUNDS( b1,    exc->zp0.n_points ) ||
+         BOUNDS( a0,    exc->zp1.n_points ) ||
+         BOUNDS( a1,    exc->zp1.n_points ) ||
+         BOUNDS( point, exc->zp2.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     /* Cramer's rule */
 
-    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
-    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+    dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x;
+    dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y;
 
-    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
-    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
+    dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x;
+    day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y;
 
-    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
-    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
-
-    CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
+    dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
+    dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
 
     discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
                    FT_MulDiv( day, dbx, 0x40 );
@@ -6999,22 +6434,26 @@
       R.x = FT_MulDiv( val, dax, discriminant );
       R.y = FT_MulDiv( val, day, discriminant );
 
-      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
-      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
+      /* XXX: Block in backwards_compatibility and/or post-IUP? */
+      exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
+      exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y;
     }
     else
     {
       /* else, take the middle of the middles of A and B */
 
-      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
-                               CUR.zp1.cur[a1].x +
-                               CUR.zp0.cur[b0].x +
-                               CUR.zp0.cur[b1].x ) / 4;
-      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
-                               CUR.zp1.cur[a1].y +
-                               CUR.zp0.cur[b0].y +
-                               CUR.zp0.cur[b1].y ) / 4;
+      /* XXX: Block in backwards_compatibility and/or post-IUP? */
+      exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
+                                exc->zp1.cur[a1].x +
+                                exc->zp0.cur[b0].x +
+                                exc->zp0.cur[b1].x ) / 4;
+      exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y +
+                                exc->zp1.cur[a1].y +
+                                exc->zp0.cur[b0].y +
+                                exc->zp0.cur[b1].y ) / 4;
     }
+
+    exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
   }
 
 
@@ -7025,7 +6464,8 @@
   /* Stack:        uint32 uint32 -->                                       */
   /*                                                                       */
   static void
-  Ins_ALIGNPTS( INS_ARG )
+  Ins_ALIGNPTS( TT_ExecContext  exc,
+                FT_Long*        args )
   {
     FT_UShort   p1, p2;
     FT_F26Dot6  distance;
@@ -7034,19 +6474,18 @@
     p1 = (FT_UShort)args[0];
     p2 = (FT_UShort)args[1];
 
-    if ( BOUNDS( p1, CUR.zp1.n_points ) ||
-         BOUNDS( p2, CUR.zp0.n_points ) )
+    if ( BOUNDS( p1, exc->zp1.n_points ) ||
+         BOUNDS( p2, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
-    distance = CUR_Func_project( CUR.zp0.cur + p2,
-                                 CUR.zp1.cur + p1 ) / 2;
+    distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
 
-    CUR_Func_move( &CUR.zp1, p1, distance );
-    CUR_Func_move( &CUR.zp0, p2, -distance );
+    exc->func_move( exc, &exc->zp1, p1, distance );
+    exc->func_move( exc, &exc->zp0, p2, -distance );
   }
 
 
@@ -7060,50 +6499,48 @@
   /* SOMETIMES, DUMBER CODE IS BETTER CODE */
 
   static void
-  Ins_IP( INS_ARG )
+  Ins_IP( TT_ExecContext  exc )
   {
     FT_F26Dot6  old_range, cur_range;
     FT_Vector*  orus_base;
     FT_Vector*  cur_base;
     FT_Int      twilight;
 
-    FT_UNUSED_ARG;
 
-
-    if ( CUR.top < CUR.GS.loop )
+    if ( exc->top < exc->GS.loop )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
     /*
      * We need to deal in a special way with the twilight zone.
-     * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
+     * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
      * for every n.
      */
-    twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
+    twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0;
 
-    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
+    if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
     if ( twilight )
-      orus_base = &CUR.zp0.org[CUR.GS.rp1];
+      orus_base = &exc->zp0.org[exc->GS.rp1];
     else
-      orus_base = &CUR.zp0.orus[CUR.GS.rp1];
+      orus_base = &exc->zp0.orus[exc->GS.rp1];
 
-    cur_base = &CUR.zp0.cur[CUR.GS.rp1];
+    cur_base = &exc->zp0.cur[exc->GS.rp1];
 
     /* XXX: There are some glyphs in some braindead but popular */
     /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
     /*      calling IP[] with bad values of rp[12].             */
     /*      Do something sane when this odd thing happens.      */
-    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
-         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
+    if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ||
+         BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
     {
       old_range = 0;
       cur_range = 0;
@@ -7111,62 +6548,60 @@
     else
     {
       if ( twilight )
-        old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
-                                       orus_base );
-      else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
-        old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
-                                       orus_base );
+        old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base );
+      else if ( exc->metrics.x_scale == exc->metrics.y_scale )
+        old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base );
       else
       {
         FT_Vector  vec;
 
 
-        vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
-                           CUR.metrics.x_scale );
-        vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
-                           CUR.metrics.y_scale );
+        vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x,
+                           exc->metrics.x_scale );
+        vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y,
+                           exc->metrics.y_scale );
 
-        old_range = CUR_fast_dualproj( &vec );
+        old_range = FAST_DUALPROJ( &vec );
       }
 
-      cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
+      cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
     }
 
-    for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
+    for ( ; exc->GS.loop > 0; --exc->GS.loop )
     {
-      FT_UInt     point = (FT_UInt)CUR.stack[--CUR.args];
+      FT_UInt     point = (FT_UInt)exc->stack[--exc->args];
       FT_F26Dot6  org_dist, cur_dist, new_dist;
 
 
       /* check point bounds */
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      if ( BOUNDS( point, exc->zp2.n_points ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
         continue;
       }
 
       if ( twilight )
-        org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
-      else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
-        org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
+        org_dist = DUALPROJ( &exc->zp2.org[point], orus_base );
+      else if ( exc->metrics.x_scale == exc->metrics.y_scale )
+        org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base );
       else
       {
         FT_Vector  vec;
 
 
-        vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x,
-                           CUR.metrics.x_scale );
-        vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y,
-                           CUR.metrics.y_scale );
+        vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x,
+                           exc->metrics.x_scale );
+        vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y,
+                           exc->metrics.y_scale );
 
-        org_dist = CUR_fast_dualproj( &vec );
+        org_dist = FAST_DUALPROJ( &vec );
       }
 
-      cur_dist = CUR_Func_project( &CUR.zp2.cur[point], cur_base );
+      cur_dist = PROJECT( &exc->zp2.cur[point], cur_base );
 
       if ( org_dist )
       {
@@ -7196,12 +6631,15 @@
       else
         new_dist = 0;
 
-      CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
+      exc->func_move( exc,
+                      &exc->zp2,
+                      (FT_UShort)point,
+                      new_dist - cur_dist );
     }
 
   Fail:
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
+    exc->GS.loop = 1;
+    exc->new_top = exc->args;
   }
 
 
@@ -7212,7 +6650,8 @@
   /* Stack:        uint32 -->                                              */
   /*                                                                       */
   static void
-  Ins_UTP( INS_ARG )
+  Ins_UTP( TT_ExecContext  exc,
+           FT_Long*        args )
   {
     FT_UShort  point;
     FT_Byte    mask;
@@ -7220,22 +6659,22 @@
 
     point = (FT_UShort)args[0];
 
-    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    if ( BOUNDS( point, exc->zp0.n_points ) )
     {
-      if ( CUR.pedantic_hinting )
-        CUR.error = FT_THROW( Invalid_Reference );
+      if ( exc->pedantic_hinting )
+        exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
     mask = 0xFF;
 
-    if ( CUR.GS.freeVector.x != 0 )
+    if ( exc->GS.freeVector.x != 0 )
       mask &= ~FT_CURVE_TAG_TOUCH_X;
 
-    if ( CUR.GS.freeVector.y != 0 )
+    if ( exc->GS.freeVector.y != 0 )
       mask &= ~FT_CURVE_TAG_TOUCH_Y;
 
-    CUR.zp0.tags[point] &= mask;
+    exc->zp0.tags[point] &= mask;
   }
 
 
@@ -7280,7 +6719,7 @@
                            FT_UInt     ref2 )
   {
     FT_UInt     i;
-    FT_F26Dot6  orus1, orus2, org1, org2, delta1, delta2;
+    FT_F26Dot6  orus1, orus2, org1, org2, cur1, cur2, delta1, delta2;
 
 
     if ( p1 > p2 )
@@ -7310,12 +6749,15 @@
 
     org1   = worker->orgs[ref1].x;
     org2   = worker->orgs[ref2].x;
-    delta1 = worker->curs[ref1].x - org1;
-    delta2 = worker->curs[ref2].x - org2;
+    cur1   = worker->curs[ref1].x;
+    cur2   = worker->curs[ref2].x;
+    delta1 = cur1 - org1;
+    delta2 = cur2 - org2;
 
-    if ( orus1 == orus2 )
+    if ( cur1 == cur2 || orus1 == orus2 )
     {
-      /* simple shift of untouched points */
+
+      /* trivial snap or shift of untouched points */
       for ( i = p1; i <= p2; i++ )
       {
         FT_F26Dot6  x = worker->orgs[i].x;
@@ -7323,9 +6765,13 @@
 
         if ( x <= org1 )
           x += delta1;
-        else
+
+        else if ( x >= org2 )
           x += delta2;
 
+        else
+          x = cur1;
+
         worker->curs[i].x = x;
       }
     }
@@ -7352,12 +6798,10 @@
           if ( !scale_valid )
           {
             scale_valid = 1;
-            scale       = FT_DivFix( org2 + delta2 - ( org1 + delta1 ),
-                                     orus2 - orus1 );
+            scale       = FT_DivFix( cur2 - cur1, orus2 - orus1 );
           }
 
-          x = ( org1 + delta1 ) +
-              FT_MulFix( worker->orus[i].x - orus1, scale );
+          x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale );
         }
         worker->curs[i].x = x;
       }
@@ -7372,7 +6816,7 @@
   /* Stack:        -->                                                     */
   /*                                                                       */
   static void
-  Ins_IUP( INS_ARG )
+  Ins_IUP( TT_ExecContext  exc )
   {
     IUP_WorkerRec  V;
     FT_Byte        mask;
@@ -7386,51 +6830,66 @@
     FT_UInt   point;         /* current point   */
     FT_Short  contour;       /* current contour */
 
-    FT_UNUSED_ARG;
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    /* Allow IUP until it has been called on both axes.  Immediately */
+    /* return on subsequent ones.                                    */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility )
+    {
+      if ( exc->iupx_called && exc->iupy_called )
+        return;
+
+      if ( exc->opcode & 1 )
+        exc->iupx_called = TRUE;
+      else
+        exc->iupy_called = TRUE;
+    }
+#endif
 
     /* ignore empty outlines */
-    if ( CUR.pts.n_contours == 0 )
+    if ( exc->pts.n_contours == 0 )
       return;
 
-    if ( CUR.opcode & 1 )
+    if ( exc->opcode & 1 )
     {
       mask   = FT_CURVE_TAG_TOUCH_X;
-      V.orgs = CUR.pts.org;
-      V.curs = CUR.pts.cur;
-      V.orus = CUR.pts.orus;
+      V.orgs = exc->pts.org;
+      V.curs = exc->pts.cur;
+      V.orus = exc->pts.orus;
     }
     else
     {
       mask   = FT_CURVE_TAG_TOUCH_Y;
-      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
-      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
-      V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
+      V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 );
+      V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 );
+      V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 );
     }
-    V.max_points = CUR.pts.n_points;
+    V.max_points = exc->pts.n_points;
 
     contour = 0;
     point   = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING  &&
-         CUR.ignore_x_mode )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         exc->ignore_x_mode          )
     {
-      CUR.iup_called = TRUE;
-      if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
+      exc->iup_called = TRUE;
+      if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
         return;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     do
     {
-      end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
+      end_point   = exc->pts.contours[contour] - exc->pts.first_point;
       first_point = point;
 
-      if ( BOUNDS ( end_point, CUR.pts.n_points ) )
-        end_point = CUR.pts.n_points - 1;
+      if ( BOUNDS( end_point, exc->pts.n_points ) )
+        end_point = exc->pts.n_points - 1;
 
-      while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
+      while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
         point++;
 
       if ( point <= end_point )
@@ -7442,7 +6901,7 @@
 
         while ( point <= end_point )
         {
-          if ( ( CUR.pts.tags[point] & mask ) != 0 )
+          if ( ( exc->pts.tags[point] & mask ) != 0 )
           {
             _iup_worker_interpolate( &V,
                                      cur_touched + 1,
@@ -7474,7 +6933,7 @@
         }
       }
       contour++;
-    } while ( contour < CUR.pts.n_contours );
+    } while ( contour < exc->pts.n_contours );
   }
 
 
@@ -7485,61 +6944,42 @@
   /* Stack:        uint32 (2 * uint32)... -->                              */
   /*                                                                       */
   static void
-  Ins_DELTAP( INS_ARG )
+  Ins_DELTAP( TT_ExecContext  exc,
+              FT_Long*        args )
   {
-    FT_ULong   k, nump;
+    FT_ULong   nump, k;
     FT_UShort  A;
-    FT_ULong   C;
+    FT_ULong   C, P;
     FT_Long    B;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_UShort  B1, B2;
 
 
-    if ( SUBPIXEL_HINTING                                        &&
-         CUR.ignore_x_mode                                       &&
-         CUR.iup_called                                          &&
-         ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
+    if ( SUBPIXEL_HINTING_INFINALITY                              &&
+         exc->ignore_x_mode                                       &&
+         exc->iup_called                                          &&
+         ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
       goto Fail;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( CUR.face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( CUR.args < n )
-      {
-        if ( CUR.pedantic_hinting )
-          CUR.error = FT_THROW( Too_Few_Arguments );
-        n = CUR.args;
-      }
-
-      CUR.args -= n;
-      CUR.new_top = CUR.args;
-      return;
-    }
-#endif
-
+    P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
                                    than once, thus UShort isn't enough */
 
     for ( k = 1; k <= nump; k++ )
     {
-      if ( CUR.args < 2 )
+      if ( exc->args < 2 )
       {
-        if ( CUR.pedantic_hinting )
-          CUR.error = FT_THROW( Too_Few_Arguments );
-        CUR.args = 0;
+        if ( exc->pedantic_hinting )
+          exc->error = FT_THROW( Too_Few_Arguments );
+        exc->args = 0;
         goto Fail;
       }
 
-      CUR.args -= 2;
+      exc->args -= 2;
 
-      A = (FT_UShort)CUR.stack[CUR.args + 1];
-      B = CUR.stack[CUR.args];
+      A = (FT_UShort)exc->stack[exc->args + 1];
+      B = exc->stack[exc->args];
 
       /* XXX: Because some popular fonts contain some invalid DeltaP */
       /*      instructions, we simply ignore them when the stacked   */
@@ -7547,11 +6987,11 @@
       /*      error.  As a delta instruction doesn't change a glyph  */
       /*      in great ways, this shouldn't be a problem.            */
 
-      if ( !BOUNDS( A, CUR.zp0.n_points ) )
+      if ( !BOUNDS( A, exc->zp0.n_points ) )
       {
         C = ( (FT_ULong)B & 0xF0 ) >> 4;
 
-        switch ( CUR.opcode )
+        switch ( exc->opcode )
         {
         case 0x5D:
           break;
@@ -7565,95 +7005,102 @@
           break;
         }
 
-        C += CUR.GS.delta_base;
+        C += exc->GS.delta_base;
 
-        if ( CURRENT_Ppem() == (FT_Long)C )
+        if ( P == C )
         {
           B = ( (FT_ULong)B & 0xF ) - 8;
           if ( B >= 0 )
             B++;
-          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+          B *= 1L << ( 6 - exc->GS.delta_shift );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-          if ( SUBPIXEL_HINTING )
+          if ( SUBPIXEL_HINTING_INFINALITY )
           {
             /*
              *  Allow delta move if
              *
-             *  - not using ignore_x_mode rendering
-             *  - glyph is specifically set to allow it
-             *  - glyph is composite and freedom vector is not subpixel
-             *    vector
+             *  - not using ignore_x_mode rendering,
+             *  - glyph is specifically set to allow it, or
+             *  - glyph is composite and freedom vector is not in subpixel
+             *    direction.
              */
-            if ( !CUR.ignore_x_mode                                   ||
-                 ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
-                 ( CUR.is_composite && CUR.GS.freeVector.y != 0 )     )
-              CUR_Func_move( &CUR.zp0, A, B );
+            if ( !exc->ignore_x_mode                                   ||
+                 ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
+                 ( exc->is_composite && exc->GS.freeVector.y != 0 )    )
+              exc->func_move( exc, &exc->zp0, A, B );
 
-            /* Otherwise apply subpixel hinting and */
-            /* compatibility mode rules             */
-            else if ( CUR.ignore_x_mode )
+            /* Otherwise, apply subpixel hinting and compatibility mode */
+            /* rules, always skipping deltas in subpixel direction.     */
+            else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 )
             {
-              if ( CUR.GS.freeVector.y != 0 )
-                B1 = (FT_UShort)CUR.zp0.cur[A].y;
-              else
-                B1 = (FT_UShort)CUR.zp0.cur[A].x;
+              /* save the y value of the point now; compare after move */
+              B1 = (FT_UShort)exc->zp0.cur[A].y;
 
-#if 0
-              /* Standard Subpixel Hinting: Allow y move.       */
-              /* This messes up dejavu and may not be needed... */
-              if ( !CUR.face->sph_compatibility_mode &&
-                   CUR.GS.freeVector.y != 0          )
-                CUR_Func_move( &CUR.zp0, A, B );
-              else
-#endif /* 0 */
+              /* Standard subpixel hinting: Allow y move for y-touched */
+              /* points.  This messes up DejaVu ...                    */
+              if ( !exc->face->sph_compatibility_mode          &&
+                   ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+                exc->func_move( exc, &exc->zp0, A, B );
 
-              /* Compatibility Mode: Allow x or y move if point touched in */
-              /* Y direction.                                              */
-              if ( CUR.face->sph_compatibility_mode                      &&
-                   !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+              /* compatibility mode */
+              else if ( exc->face->sph_compatibility_mode                        &&
+                        !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
               {
-                /* save the y value of the point now; compare after move */
-                B1 = (FT_UShort)CUR.zp0.cur[A].y;
-
-                if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+                if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
                   B = FT_PIX_ROUND( B1 + B ) - B1;
 
                 /* Allow delta move if using sph_compatibility_mode,   */
                 /* IUP has not been called, and point is touched on Y. */
-                if ( !CUR.iup_called                            &&
-                     ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
-                  CUR_Func_move( &CUR.zp0, A, B );
+                if ( !exc->iup_called                            &&
+                     ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+                  exc->func_move( exc, &exc->zp0, A, B );
               }
 
-              B2 = (FT_UShort)CUR.zp0.cur[A].y;
+              B2 = (FT_UShort)exc->zp0.cur[A].y;
 
               /* Reverse this move if it results in a disallowed move */
-              if ( CUR.GS.freeVector.y != 0                           &&
-                   ( ( CUR.face->sph_compatibility_mode           &&
+              if ( exc->GS.freeVector.y != 0                          &&
+                   ( ( exc->face->sph_compatibility_mode          &&
                        ( B1 & 63 ) == 0                           &&
                        ( B2 & 63 ) != 0                           ) ||
-                     ( ( CUR.sph_tweak_flags                    &
+                     ( ( exc->sph_tweak_flags                   &
                          SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
                        ( B1 & 63 ) != 0                           &&
                        ( B2 & 63 ) != 0                           ) ) )
-                CUR_Func_move( &CUR.zp0, A, -B );
+                exc->func_move( exc, &exc->zp0, A, -B );
             }
           }
           else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-            CUR_Func_move( &CUR.zp0, A, B );
+          {
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+            /* See `ttinterp.h' for details on backwards compatibility */
+            /* mode.                                                   */
+            if ( SUBPIXEL_HINTING_MINIMAL     &&
+                 exc->backwards_compatibility )
+            {
+              if ( !( exc->iupx_called && exc->iupy_called )              &&
+                   ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+                     ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y )        ) )
+                exc->func_move( exc, &exc->zp0, A, B );
+            }
+            else
+#endif
+              exc->func_move( exc, &exc->zp0, A, B );
+          }
         }
       }
       else
-        if ( CUR.pedantic_hinting )
-          CUR.error = FT_THROW( Invalid_Reference );
+        if ( exc->pedantic_hinting )
+          exc->error = FT_THROW( Invalid_Reference );
     }
 
   Fail:
-    CUR.new_top = CUR.args;
+    exc->new_top = exc->args;
   }
 
 
@@ -7664,55 +7111,37 @@
   /* Stack:        uint32 (2 * uint32)... -->                              */
   /*                                                                       */
   static void
-  Ins_DELTAC( INS_ARG )
+  Ins_DELTAC( TT_ExecContext  exc,
+              FT_Long*        args )
   {
     FT_ULong  nump, k;
-    FT_ULong  A, C;
+    FT_ULong  A, C, P;
     FT_Long   B;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( CUR.face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( CUR.args < n )
-      {
-        if ( CUR.pedantic_hinting )
-          CUR.error = FT_THROW( Too_Few_Arguments );
-        n = CUR.args;
-      }
-
-      CUR.args -= n;
-      CUR.new_top = CUR.args;
-      return;
-    }
-#endif
-
+    P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];
 
     for ( k = 1; k <= nump; k++ )
     {
-      if ( CUR.args < 2 )
+      if ( exc->args < 2 )
       {
-        if ( CUR.pedantic_hinting )
-          CUR.error = FT_THROW( Too_Few_Arguments );
-        CUR.args = 0;
+        if ( exc->pedantic_hinting )
+          exc->error = FT_THROW( Too_Few_Arguments );
+        exc->args = 0;
         goto Fail;
       }
 
-      CUR.args -= 2;
+      exc->args -= 2;
 
-      A = (FT_ULong)CUR.stack[CUR.args + 1];
-      B = CUR.stack[CUR.args];
+      A = (FT_ULong)exc->stack[exc->args + 1];
+      B = exc->stack[exc->args];
 
-      if ( BOUNDSL( A, CUR.cvtSize ) )
+      if ( BOUNDSL( A, exc->cvtSize ) )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Invalid_Reference );
+          exc->error = FT_THROW( Invalid_Reference );
           return;
         }
       }
@@ -7720,7 +7149,7 @@
       {
         C = ( (FT_ULong)B & 0xF0 ) >> 4;
 
-        switch ( CUR.opcode )
+        switch ( exc->opcode )
         {
         case 0x73:
           break;
@@ -7734,22 +7163,22 @@
           break;
         }
 
-        C += CUR.GS.delta_base;
+        C += exc->GS.delta_base;
 
-        if ( CURRENT_Ppem() == (FT_Long)C )
+        if ( P == C )
         {
           B = ( (FT_ULong)B & 0xF ) - 8;
           if ( B >= 0 )
             B++;
-          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+          B *= 1L << ( 6 - exc->GS.delta_shift );
 
-          CUR_Func_move_cvt( A, B );
+          exc->func_move_cvt( exc, A, B );
         }
       }
     }
 
   Fail:
-    CUR.new_top = CUR.args;
+    exc->new_top = exc->args;
   }
 
 
@@ -7766,72 +7195,152 @@
   /* Opcode range: 0x88                                                    */
   /* Stack:        uint32 --> uint32                                       */
   /*                                                                       */
+  /* XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May     */
+  /*      2015) not documented in the OpenType specification.              */
+  /*                                                                       */
+  /*      Selector bit 11 is incorrectly described as bit 8, while the     */
+  /*      real meaning of bit 8 (vertical LCD subpixels) stays             */
+  /*      undocumented.  The same mistake can be found in Greg Hitchcock's */
+  /*      whitepaper.                                                      */
+  /*                                                                       */
   static void
-  Ins_GETINFO( INS_ARG )
+  Ins_GETINFO( TT_ExecContext  exc,
+               FT_Long*        args )
   {
-    FT_Long  K;
+    FT_Long    K;
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
 
     K = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /********************************/
     /* RASTERIZER VERSION           */
     /* Selector Bit:  0             */
     /* Return Bit(s): 0-7           */
     /*                              */
-    if ( SUBPIXEL_HINTING     &&
-         ( args[0] & 1 ) != 0 &&
-         CUR.ignore_x_mode    )
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         ( args[0] & 1 ) != 0        &&
+         exc->subpixel_hinting       )
     {
-      K = CUR.rasterizer_version;
-      FT_TRACE7(( "Setting rasterizer version %d\n",
-                  CUR.rasterizer_version ));
+      if ( exc->ignore_x_mode )
+      {
+        /* if in ClearType backwards compatibility mode,        */
+        /* we sometimes change the TrueType version dynamically */
+        K = exc->rasterizer_version;
+        FT_TRACE6(( "Setting rasterizer version %d\n",
+                    exc->rasterizer_version ));
+      }
+      else
+        K = TT_INTERPRETER_VERSION_38;
     }
     else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
       if ( ( args[0] & 1 ) != 0 )
-        K = TT_INTERPRETER_VERSION_35;
+        K = driver->interpreter_version;
 
     /********************************/
     /* GLYPH ROTATED                */
     /* Selector Bit:  1             */
     /* Return Bit(s): 8             */
     /*                              */
-    if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
-      K |= 0x80;
+    if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
+      K |= 1 << 8;
 
     /********************************/
     /* GLYPH STRETCHED              */
     /* Selector Bit:  2             */
     /* Return Bit(s): 9             */
     /*                              */
-    if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
-      K |= 1 << 8;
+    if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
+      K |= 1 << 9;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    /********************************/
+    /* VARIATION GLYPH              */
+    /* Selector Bit:  3             */
+    /* Return Bit(s): 10            */
+    /*                              */
+    /* XXX: UNDOCUMENTED!           */
+    if ( (args[0] & 8 ) != 0 && exc->face->blend )
+      K |= 1 << 10;
+#endif
 
     /********************************/
-    /* HINTING FOR GRAYSCALE        */
+    /* BI-LEVEL HINTING AND         */
+    /* GRAYSCALE RENDERING          */
     /* Selector Bit:  5             */
     /* Return Bit(s): 12            */
     /*                              */
-    if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
+    if ( ( args[0] & 32 ) != 0 && exc->grayscale )
       K |= 1 << 12;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( SUBPIXEL_HINTING_MINIMAL )
+    {
+      /********************************/
+      /* HINTING FOR SUBPIXEL         */
+      /* Selector Bit:  6             */
+      /* Return Bit(s): 13            */
+      /*                              */
+      /* v40 does subpixel hinting by default. */
+      if ( ( args[0] & 64 ) != 0 )
+        K |= 1 << 13;
 
-    if ( SUBPIXEL_HINTING                                    &&
-         CUR.ignore_x_mode                                   &&
-         CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
+      /********************************/
+      /* VERTICAL LCD SUBPIXELS?      */
+      /* Selector Bit:  8             */
+      /* Return Bit(s): 15            */
+      /*                              */
+      if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
+        K |= 1 << 15;
+
+      /********************************/
+      /* SUBPIXEL POSITIONED?         */
+      /* Selector Bit:  10            */
+      /* Return Bit(s): 17            */
+      /*                              */
+      /* XXX: FreeType supports it, dependent on what client does? */
+      if ( ( args[0] & 1024 ) != 0 )
+        K |= 1 << 17;
+
+      /********************************/
+      /* SYMMETRICAL SMOOTHING        */
+      /* Selector Bit:  11            */
+      /* Return Bit(s): 18            */
+      /*                              */
+      /* The only smoothing method FreeType supports unless someone sets */
+      /* FT_LOAD_TARGET_MONO.                                            */
+      if ( ( args[0] & 2048 ) != 0 )
+        K |= 1 << 18;
+
+      /********************************/
+      /* CLEARTYPE HINTING AND        */
+      /* GRAYSCALE RENDERING          */
+      /* Selector Bit:  12            */
+      /* Return Bit(s): 19            */
+      /*                              */
+      /* Grayscale rendering is what FreeType does anyway unless someone */
+      /* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V)              */
+      if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
+        K |= 1 << 19;
+    }
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+
+    if ( SUBPIXEL_HINTING_INFINALITY                          &&
+         exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
     {
 
-      if ( CUR.rasterizer_version >= 37 )
+      if ( exc->rasterizer_version >= 37 )
       {
         /********************************/
         /* HINTING FOR SUBPIXEL         */
         /* Selector Bit:  6             */
         /* Return Bit(s): 13            */
         /*                              */
-        if ( ( args[0] & 64 ) != 0 && CUR.subpixel )
+        if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting )
           K |= 1 << 13;
 
         /********************************/
@@ -7840,16 +7349,16 @@
         /* Return Bit(s): 14            */
         /*                              */
         /* Functionality still needs to be added */
-        if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths )
+        if ( ( args[0] & 128 ) != 0 && exc->compatible_widths )
           K |= 1 << 14;
 
         /********************************/
-        /* SYMMETRICAL SMOOTHING        */
+        /* VERTICAL LCD SUBPIXELS?      */
         /* Selector Bit:  8             */
         /* Return Bit(s): 15            */
         /*                              */
         /* Functionality still needs to be added */
-        if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing )
+        if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
           K |= 1 << 15;
 
         /********************************/
@@ -7858,10 +7367,10 @@
         /* Return Bit(s): 16            */
         /*                              */
         /* Functionality still needs to be added */
-        if ( ( args[0] & 512 ) != 0 && CUR.bgr )
+        if ( ( args[0] & 512 ) != 0 && exc->bgr )
           K |= 1 << 16;
 
-        if ( CUR.rasterizer_version >= 38 )
+        if ( exc->rasterizer_version >= 38 )
         {
           /********************************/
           /* SUBPIXEL POSITIONED?         */
@@ -7869,344 +7378,125 @@
           /* Return Bit(s): 17            */
           /*                              */
           /* Functionality still needs to be added */
-          if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned )
+          if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned )
             K |= 1 << 17;
+
+          /********************************/
+          /* SYMMETRICAL SMOOTHING        */
+          /* Selector Bit:  11            */
+          /* Return Bit(s): 18            */
+          /*                              */
+          /* Functionality still needs to be added */
+          if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing )
+            K |= 1 << 18;
+
+          /********************************/
+          /* GRAY CLEARTYPE               */
+          /* Selector Bit:  12            */
+          /* Return Bit(s): 19            */
+          /*                              */
+          /* Functionality still needs to be added */
+          if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype )
+            K |= 1 << 19;
         }
       }
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = K;
   }
 
 
-  static void
-  Ins_UNKNOWN( INS_ARG )
-  {
-    TT_DefRecord*  def   = CUR.IDefs;
-    TT_DefRecord*  limit = def + CUR.numIDefs;
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    FT_UNUSED_ARG;
+  /*************************************************************************/
+  /*                                                                       */
+  /* GETVARIATION[]: get normalized variation (blend) coordinates          */
+  /* Opcode range: 0x91                                                    */
+  /* Stack:        --> f2.14...                                            */
+  /*                                                                       */
+  /* XXX: UNDOCUMENTED!  There is no official documentation from Apple for */
+  /*      this bytecode instruction.  Active only if a font has GX         */
+  /*      variation axes.                                                  */
+  /*                                                                       */
+  static void
+  Ins_GETVARIATION( TT_ExecContext  exc,
+                    FT_Long*        args )
+  {
+    FT_UInt    num_axes = exc->face->blend->num_axis;
+    FT_Fixed*  coords   = exc->face->blend->normalizedcoords;
+
+    FT_UInt  i;
+
+
+    if ( BOUNDS( num_axes, exc->stackSize + 1 - exc->top ) )
+    {
+      exc->error = FT_THROW( Stack_Overflow );
+      return;
+    }
+
+    for ( i = 0; i < num_axes; i++ )
+      args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GETDATA[]:    no idea what this is good for                           */
+  /* Opcode range: 0x92                                                    */
+  /* Stack:        --> 17                                                  */
+  /*                                                                       */
+  /* XXX: UNDOCUMENTED!  There is no documentation from Apple for this     */
+  /*      very weird bytecode instruction.                                 */
+  /*                                                                       */
+  static void
+  Ins_GETDATA( FT_Long*  args )
+  {
+    args[0] = 17;
+  }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+  static void
+  Ins_UNKNOWN( TT_ExecContext  exc )
+  {
+    TT_DefRecord*  def   = exc->IDefs;
+    TT_DefRecord*  limit = def + exc->numIDefs;
 
 
     for ( ; def < limit; def++ )
     {
-      if ( (FT_Byte)def->opc == CUR.opcode && def->active )
+      if ( (FT_Byte)def->opc == exc->opcode && def->active )
       {
         TT_CallRec*  call;
 
 
-        if ( CUR.callTop >= CUR.callSize )
+        if ( exc->callTop >= exc->callSize )
         {
-          CUR.error = FT_THROW( Stack_Overflow );
+          exc->error = FT_THROW( Stack_Overflow );
           return;
         }
 
-        call = CUR.callStack + CUR.callTop++;
+        call = exc->callStack + exc->callTop++;
 
-        call->Caller_Range = CUR.curRange;
-        call->Caller_IP    = CUR.IP + 1;
+        call->Caller_Range = exc->curRange;
+        call->Caller_IP    = exc->IP + 1;
         call->Cur_Count    = 1;
         call->Def          = def;
 
-        INS_Goto_CodeRange( def->range, def->start );
+        Ins_Goto_CodeRange( exc, def->range, def->start );
 
-        CUR.step_ins = FALSE;
+        exc->step_ins = FALSE;
         return;
       }
     }
 
-    CUR.error = FT_THROW( Invalid_Opcode );
+    exc->error = FT_THROW( Invalid_Opcode );
   }
 
 
-#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
-
-  static
-  TInstruction_Function  Instruct_Dispatch[256] =
-  {
-    /* Opcodes are gathered in groups of 16. */
-    /* Please keep the spaces as they are.   */
-
-    /*  SVTCA  y  */  Ins_SVTCA,
-    /*  SVTCA  x  */  Ins_SVTCA,
-    /*  SPvTCA y  */  Ins_SPVTCA,
-    /*  SPvTCA x  */  Ins_SPVTCA,
-    /*  SFvTCA y  */  Ins_SFVTCA,
-    /*  SFvTCA x  */  Ins_SFVTCA,
-    /*  SPvTL //  */  Ins_SPVTL,
-    /*  SPvTL +   */  Ins_SPVTL,
-    /*  SFvTL //  */  Ins_SFVTL,
-    /*  SFvTL +   */  Ins_SFVTL,
-    /*  SPvFS     */  Ins_SPVFS,
-    /*  SFvFS     */  Ins_SFVFS,
-    /*  GPV       */  Ins_GPV,
-    /*  GFV       */  Ins_GFV,
-    /*  SFvTPv    */  Ins_SFVTPV,
-    /*  ISECT     */  Ins_ISECT,
-
-    /*  SRP0      */  Ins_SRP0,
-    /*  SRP1      */  Ins_SRP1,
-    /*  SRP2      */  Ins_SRP2,
-    /*  SZP0      */  Ins_SZP0,
-    /*  SZP1      */  Ins_SZP1,
-    /*  SZP2      */  Ins_SZP2,
-    /*  SZPS      */  Ins_SZPS,
-    /*  SLOOP     */  Ins_SLOOP,
-    /*  RTG       */  Ins_RTG,
-    /*  RTHG      */  Ins_RTHG,
-    /*  SMD       */  Ins_SMD,
-    /*  ELSE      */  Ins_ELSE,
-    /*  JMPR      */  Ins_JMPR,
-    /*  SCvTCi    */  Ins_SCVTCI,
-    /*  SSwCi     */  Ins_SSWCI,
-    /*  SSW       */  Ins_SSW,
-
-    /*  DUP       */  Ins_DUP,
-    /*  POP       */  Ins_POP,
-    /*  CLEAR     */  Ins_CLEAR,
-    /*  SWAP      */  Ins_SWAP,
-    /*  DEPTH     */  Ins_DEPTH,
-    /*  CINDEX    */  Ins_CINDEX,
-    /*  MINDEX    */  Ins_MINDEX,
-    /*  AlignPTS  */  Ins_ALIGNPTS,
-    /*  INS_0x28  */  Ins_UNKNOWN,
-    /*  UTP       */  Ins_UTP,
-    /*  LOOPCALL  */  Ins_LOOPCALL,
-    /*  CALL      */  Ins_CALL,
-    /*  FDEF      */  Ins_FDEF,
-    /*  ENDF      */  Ins_ENDF,
-    /*  MDAP[0]   */  Ins_MDAP,
-    /*  MDAP[1]   */  Ins_MDAP,
-
-    /*  IUP[0]    */  Ins_IUP,
-    /*  IUP[1]    */  Ins_IUP,
-    /*  SHP[0]    */  Ins_SHP,
-    /*  SHP[1]    */  Ins_SHP,
-    /*  SHC[0]    */  Ins_SHC,
-    /*  SHC[1]    */  Ins_SHC,
-    /*  SHZ[0]    */  Ins_SHZ,
-    /*  SHZ[1]    */  Ins_SHZ,
-    /*  SHPIX     */  Ins_SHPIX,
-    /*  IP        */  Ins_IP,
-    /*  MSIRP[0]  */  Ins_MSIRP,
-    /*  MSIRP[1]  */  Ins_MSIRP,
-    /*  AlignRP   */  Ins_ALIGNRP,
-    /*  RTDG      */  Ins_RTDG,
-    /*  MIAP[0]   */  Ins_MIAP,
-    /*  MIAP[1]   */  Ins_MIAP,
-
-    /*  NPushB    */  Ins_NPUSHB,
-    /*  NPushW    */  Ins_NPUSHW,
-    /*  WS        */  Ins_WS,
-    /*  RS        */  Ins_RS,
-    /*  WCvtP     */  Ins_WCVTP,
-    /*  RCvt      */  Ins_RCVT,
-    /*  GC[0]     */  Ins_GC,
-    /*  GC[1]     */  Ins_GC,
-    /*  SCFS      */  Ins_SCFS,
-    /*  MD[0]     */  Ins_MD,
-    /*  MD[1]     */  Ins_MD,
-    /*  MPPEM     */  Ins_MPPEM,
-    /*  MPS       */  Ins_MPS,
-    /*  FlipON    */  Ins_FLIPON,
-    /*  FlipOFF   */  Ins_FLIPOFF,
-    /*  DEBUG     */  Ins_DEBUG,
-
-    /*  LT        */  Ins_LT,
-    /*  LTEQ      */  Ins_LTEQ,
-    /*  GT        */  Ins_GT,
-    /*  GTEQ      */  Ins_GTEQ,
-    /*  EQ        */  Ins_EQ,
-    /*  NEQ       */  Ins_NEQ,
-    /*  ODD       */  Ins_ODD,
-    /*  EVEN      */  Ins_EVEN,
-    /*  IF        */  Ins_IF,
-    /*  EIF       */  Ins_EIF,
-    /*  AND       */  Ins_AND,
-    /*  OR        */  Ins_OR,
-    /*  NOT       */  Ins_NOT,
-    /*  DeltaP1   */  Ins_DELTAP,
-    /*  SDB       */  Ins_SDB,
-    /*  SDS       */  Ins_SDS,
-
-    /*  ADD       */  Ins_ADD,
-    /*  SUB       */  Ins_SUB,
-    /*  DIV       */  Ins_DIV,
-    /*  MUL       */  Ins_MUL,
-    /*  ABS       */  Ins_ABS,
-    /*  NEG       */  Ins_NEG,
-    /*  FLOOR     */  Ins_FLOOR,
-    /*  CEILING   */  Ins_CEILING,
-    /*  ROUND[0]  */  Ins_ROUND,
-    /*  ROUND[1]  */  Ins_ROUND,
-    /*  ROUND[2]  */  Ins_ROUND,
-    /*  ROUND[3]  */  Ins_ROUND,
-    /*  NROUND[0] */  Ins_NROUND,
-    /*  NROUND[1] */  Ins_NROUND,
-    /*  NROUND[2] */  Ins_NROUND,
-    /*  NROUND[3] */  Ins_NROUND,
-
-    /*  WCvtF     */  Ins_WCVTF,
-    /*  DeltaP2   */  Ins_DELTAP,
-    /*  DeltaP3   */  Ins_DELTAP,
-    /*  DeltaCn[0] */ Ins_DELTAC,
-    /*  DeltaCn[1] */ Ins_DELTAC,
-    /*  DeltaCn[2] */ Ins_DELTAC,
-    /*  SROUND    */  Ins_SROUND,
-    /*  S45Round  */  Ins_S45ROUND,
-    /*  JROT      */  Ins_JROT,
-    /*  JROF      */  Ins_JROF,
-    /*  ROFF      */  Ins_ROFF,
-    /*  INS_0x7B  */  Ins_UNKNOWN,
-    /*  RUTG      */  Ins_RUTG,
-    /*  RDTG      */  Ins_RDTG,
-    /*  SANGW     */  Ins_SANGW,
-    /*  AA        */  Ins_AA,
-
-    /*  FlipPT    */  Ins_FLIPPT,
-    /*  FlipRgON  */  Ins_FLIPRGON,
-    /*  FlipRgOFF */  Ins_FLIPRGOFF,
-    /*  INS_0x83  */  Ins_UNKNOWN,
-    /*  INS_0x84  */  Ins_UNKNOWN,
-    /*  ScanCTRL  */  Ins_SCANCTRL,
-    /*  SDPVTL[0] */  Ins_SDPVTL,
-    /*  SDPVTL[1] */  Ins_SDPVTL,
-    /*  GetINFO   */  Ins_GETINFO,
-    /*  IDEF      */  Ins_IDEF,
-    /*  ROLL      */  Ins_ROLL,
-    /*  MAX       */  Ins_MAX,
-    /*  MIN       */  Ins_MIN,
-    /*  ScanTYPE  */  Ins_SCANTYPE,
-    /*  InstCTRL  */  Ins_INSTCTRL,
-    /*  INS_0x8F  */  Ins_UNKNOWN,
-
-    /*  INS_0x90  */   Ins_UNKNOWN,
-    /*  INS_0x91  */   Ins_UNKNOWN,
-    /*  INS_0x92  */   Ins_UNKNOWN,
-    /*  INS_0x93  */   Ins_UNKNOWN,
-    /*  INS_0x94  */   Ins_UNKNOWN,
-    /*  INS_0x95  */   Ins_UNKNOWN,
-    /*  INS_0x96  */   Ins_UNKNOWN,
-    /*  INS_0x97  */   Ins_UNKNOWN,
-    /*  INS_0x98  */   Ins_UNKNOWN,
-    /*  INS_0x99  */   Ins_UNKNOWN,
-    /*  INS_0x9A  */   Ins_UNKNOWN,
-    /*  INS_0x9B  */   Ins_UNKNOWN,
-    /*  INS_0x9C  */   Ins_UNKNOWN,
-    /*  INS_0x9D  */   Ins_UNKNOWN,
-    /*  INS_0x9E  */   Ins_UNKNOWN,
-    /*  INS_0x9F  */   Ins_UNKNOWN,
-
-    /*  INS_0xA0  */   Ins_UNKNOWN,
-    /*  INS_0xA1  */   Ins_UNKNOWN,
-    /*  INS_0xA2  */   Ins_UNKNOWN,
-    /*  INS_0xA3  */   Ins_UNKNOWN,
-    /*  INS_0xA4  */   Ins_UNKNOWN,
-    /*  INS_0xA5  */   Ins_UNKNOWN,
-    /*  INS_0xA6  */   Ins_UNKNOWN,
-    /*  INS_0xA7  */   Ins_UNKNOWN,
-    /*  INS_0xA8  */   Ins_UNKNOWN,
-    /*  INS_0xA9  */   Ins_UNKNOWN,
-    /*  INS_0xAA  */   Ins_UNKNOWN,
-    /*  INS_0xAB  */   Ins_UNKNOWN,
-    /*  INS_0xAC  */   Ins_UNKNOWN,
-    /*  INS_0xAD  */   Ins_UNKNOWN,
-    /*  INS_0xAE  */   Ins_UNKNOWN,
-    /*  INS_0xAF  */   Ins_UNKNOWN,
-
-    /*  PushB[0]  */  Ins_PUSHB,
-    /*  PushB[1]  */  Ins_PUSHB,
-    /*  PushB[2]  */  Ins_PUSHB,
-    /*  PushB[3]  */  Ins_PUSHB,
-    /*  PushB[4]  */  Ins_PUSHB,
-    /*  PushB[5]  */  Ins_PUSHB,
-    /*  PushB[6]  */  Ins_PUSHB,
-    /*  PushB[7]  */  Ins_PUSHB,
-    /*  PushW[0]  */  Ins_PUSHW,
-    /*  PushW[1]  */  Ins_PUSHW,
-    /*  PushW[2]  */  Ins_PUSHW,
-    /*  PushW[3]  */  Ins_PUSHW,
-    /*  PushW[4]  */  Ins_PUSHW,
-    /*  PushW[5]  */  Ins_PUSHW,
-    /*  PushW[6]  */  Ins_PUSHW,
-    /*  PushW[7]  */  Ins_PUSHW,
-
-    /*  MDRP[00]  */  Ins_MDRP,
-    /*  MDRP[01]  */  Ins_MDRP,
-    /*  MDRP[02]  */  Ins_MDRP,
-    /*  MDRP[03]  */  Ins_MDRP,
-    /*  MDRP[04]  */  Ins_MDRP,
-    /*  MDRP[05]  */  Ins_MDRP,
-    /*  MDRP[06]  */  Ins_MDRP,
-    /*  MDRP[07]  */  Ins_MDRP,
-    /*  MDRP[08]  */  Ins_MDRP,
-    /*  MDRP[09]  */  Ins_MDRP,
-    /*  MDRP[10]  */  Ins_MDRP,
-    /*  MDRP[11]  */  Ins_MDRP,
-    /*  MDRP[12]  */  Ins_MDRP,
-    /*  MDRP[13]  */  Ins_MDRP,
-    /*  MDRP[14]  */  Ins_MDRP,
-    /*  MDRP[15]  */  Ins_MDRP,
-
-    /*  MDRP[16]  */  Ins_MDRP,
-    /*  MDRP[17]  */  Ins_MDRP,
-    /*  MDRP[18]  */  Ins_MDRP,
-    /*  MDRP[19]  */  Ins_MDRP,
-    /*  MDRP[20]  */  Ins_MDRP,
-    /*  MDRP[21]  */  Ins_MDRP,
-    /*  MDRP[22]  */  Ins_MDRP,
-    /*  MDRP[23]  */  Ins_MDRP,
-    /*  MDRP[24]  */  Ins_MDRP,
-    /*  MDRP[25]  */  Ins_MDRP,
-    /*  MDRP[26]  */  Ins_MDRP,
-    /*  MDRP[27]  */  Ins_MDRP,
-    /*  MDRP[28]  */  Ins_MDRP,
-    /*  MDRP[29]  */  Ins_MDRP,
-    /*  MDRP[30]  */  Ins_MDRP,
-    /*  MDRP[31]  */  Ins_MDRP,
-
-    /*  MIRP[00]  */  Ins_MIRP,
-    /*  MIRP[01]  */  Ins_MIRP,
-    /*  MIRP[02]  */  Ins_MIRP,
-    /*  MIRP[03]  */  Ins_MIRP,
-    /*  MIRP[04]  */  Ins_MIRP,
-    /*  MIRP[05]  */  Ins_MIRP,
-    /*  MIRP[06]  */  Ins_MIRP,
-    /*  MIRP[07]  */  Ins_MIRP,
-    /*  MIRP[08]  */  Ins_MIRP,
-    /*  MIRP[09]  */  Ins_MIRP,
-    /*  MIRP[10]  */  Ins_MIRP,
-    /*  MIRP[11]  */  Ins_MIRP,
-    /*  MIRP[12]  */  Ins_MIRP,
-    /*  MIRP[13]  */  Ins_MIRP,
-    /*  MIRP[14]  */  Ins_MIRP,
-    /*  MIRP[15]  */  Ins_MIRP,
-
-    /*  MIRP[16]  */  Ins_MIRP,
-    /*  MIRP[17]  */  Ins_MIRP,
-    /*  MIRP[18]  */  Ins_MIRP,
-    /*  MIRP[19]  */  Ins_MIRP,
-    /*  MIRP[20]  */  Ins_MIRP,
-    /*  MIRP[21]  */  Ins_MIRP,
-    /*  MIRP[22]  */  Ins_MIRP,
-    /*  MIRP[23]  */  Ins_MIRP,
-    /*  MIRP[24]  */  Ins_MIRP,
-    /*  MIRP[25]  */  Ins_MIRP,
-    /*  MIRP[26]  */  Ins_MIRP,
-    /*  MIRP[27]  */  Ins_MIRP,
-    /*  MIRP[28]  */  Ins_MIRP,
-    /*  MIRP[29]  */  Ins_MIRP,
-    /*  MIRP[30]  */  Ins_MIRP,
-    /*  MIRP[31]  */  Ins_MIRP
-  };
-
-
-#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* RUN                                                                   */
@@ -8234,8 +7524,6 @@
   /*                                                                       */
   /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
   /*                                                                       */
-  /*  Instructions appear in the specification's order.                    */
-  /*                                                                       */
   /*************************************************************************/
 
 
@@ -8247,7 +7535,7 @@
     FT_Long    ins_counter = 0;  /* executed instructions counter */
     FT_UShort  i;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Byte    opcode_pattern[1][2] = {
                   /* #8 TypeMan Talk Align */
                   {
@@ -8258,106 +7546,150 @@
     FT_UShort  opcode_patterns   = 1;
     FT_UShort  opcode_pointer[1] = { 0 };
     FT_UShort  opcode_size[1]    = { 1 };
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    cur = *exc;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    exc->iup_called = FALSE;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* Toggle backwards compatibility according to what font says, except  */
+    /* when it's a `tricky' font that heavily relies on the interpreter to */
+    /* render glyphs correctly, e.g. DFKai-SB.  Backwards compatibility    */
+    /* hacks may break it.                                                 */
+    if ( SUBPIXEL_HINTING_MINIMAL          &&
+         !FT_IS_TRICKY( &exc->face->root ) )
+      exc->backwards_compatibility = !( exc->GS.instruct_control & 4 );
+    else
+      exc->backwards_compatibility = FALSE;
+
+    exc->iupx_called = FALSE;
+    exc->iupy_called = FALSE;
 #endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    CUR.iup_called = FALSE;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-    /* set CVT functions */
-    CUR.tt_metrics.ratio = 0;
-    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+    /* set PPEM and CVT functions */
+    exc->tt_metrics.ratio = 0;
+    if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
     {
       /* non-square pixels, use the stretched routines */
-      CUR.func_read_cvt  = Read_CVT_Stretched;
-      CUR.func_write_cvt = Write_CVT_Stretched;
-      CUR.func_move_cvt  = Move_CVT_Stretched;
+      exc->func_cur_ppem  = Current_Ppem_Stretched;
+      exc->func_read_cvt  = Read_CVT_Stretched;
+      exc->func_write_cvt = Write_CVT_Stretched;
+      exc->func_move_cvt  = Move_CVT_Stretched;
     }
     else
     {
       /* square pixels, use normal routines */
-      CUR.func_read_cvt  = Read_CVT;
-      CUR.func_write_cvt = Write_CVT;
-      CUR.func_move_cvt  = Move_CVT;
+      exc->func_cur_ppem  = Current_Ppem;
+      exc->func_read_cvt  = Read_CVT;
+      exc->func_write_cvt = Write_CVT;
+      exc->func_move_cvt  = Move_CVT;
     }
 
-    COMPUTE_Funcs();
-    COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+    Compute_Funcs( exc );
+    Compute_Round( exc, (FT_Byte)exc->GS.round_state );
 
     do
     {
-      CUR.opcode = CUR.code[CUR.IP];
+      exc->opcode = exc->code[exc->IP];
 
-      FT_TRACE7(( "  " ));
-      FT_TRACE7(( opcode_name[CUR.opcode] ));
-      FT_TRACE7(( "\n" ));
-
-      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+#ifdef FT_DEBUG_LEVEL_TRACE
       {
-        if ( CUR.IP + 1 >= CUR.codeSize )
+        FT_Long  cnt = FT_MIN( 8, exc->top );
+        FT_Long  n;
+
+
+        /* if tracing level is 7, show current code position */
+        /* and the first few stack elements also             */
+        FT_TRACE6(( "  " ));
+        FT_TRACE7(( "%06d ", exc->IP ));
+        FT_TRACE6(( opcode_name[exc->opcode] + 2 ));
+        FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A'
+                              ? 2
+                              : 12 - ( *opcode_name[exc->opcode] - '0' ),
+                              "#" ));
+        for ( n = 1; n <= cnt; n++ )
+          FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
+        FT_TRACE6(( "\n" ));
+      }
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+      if ( ( exc->length = opcode_length[exc->opcode] ) < 0 )
+      {
+        if ( exc->IP + 1 >= exc->codeSize )
           goto LErrorCodeOverflow_;
 
-        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+        exc->length = 2 - exc->length * exc->code[exc->IP + 1];
       }
 
-      if ( CUR.IP + CUR.length > CUR.codeSize )
+      if ( exc->IP + exc->length > exc->codeSize )
         goto LErrorCodeOverflow_;
 
       /* First, let's check for empty stack and overflow */
-      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+      exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 );
 
       /* `args' is the top of the stack once arguments have been popped. */
       /* One can also interpret it as the index of the last argument.    */
-      if ( CUR.args < 0 )
+      if ( exc->args < 0 )
       {
-        if ( CUR.pedantic_hinting )
+        if ( exc->pedantic_hinting )
         {
-          CUR.error = FT_THROW( Too_Few_Arguments );
+          exc->error = FT_THROW( Too_Few_Arguments );
           goto LErrorLabel_;
         }
 
         /* push zeroes onto the stack */
-        for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
-          CUR.stack[i] = 0;
-        CUR.args = 0;
+        for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ )
+          exc->stack[i] = 0;
+        exc->args = 0;
       }
 
-      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+      if ( exc->opcode == 0x91 )
+      {
+        /* this is very special: GETVARIATION returns */
+        /* a variable number of arguments             */
+
+        /* it is the job of the application to `activate' GX handling, */
+        /* this is, calling any of the GX API functions on the current */
+        /* font to select a variation instance                         */
+        if ( exc->face->blend )
+          exc->new_top = exc->args + exc->face->blend->num_axis;
+      }
+      else
+#endif
+        exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 );
 
       /* `new_top' is the new top of the stack, after the instruction's */
       /* execution.  `top' will be set to `new_top' after the `switch'  */
       /* statement.                                                     */
-      if ( CUR.new_top > CUR.stackSize )
+      if ( exc->new_top > exc->stackSize )
       {
-        CUR.error = FT_THROW( Stack_Overflow );
+        exc->error = FT_THROW( Stack_Overflow );
         goto LErrorLabel_;
       }
 
-      CUR.step_ins = TRUE;
-      CUR.error    = FT_Err_Ok;
+      exc->step_ins = TRUE;
+      exc->error    = FT_Err_Ok;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-      if ( SUBPIXEL_HINTING )
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
-          if ( opcode_pointer[i] < opcode_size[i]                 &&
-               CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+          if ( opcode_pointer[i] < opcode_size[i]                  &&
+               exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
           {
             opcode_pointer[i] += 1;
 
             if ( opcode_pointer[i] == opcode_size[i] )
             {
-              FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n",
+              FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n",
                           i,
-                          CUR.face->root.family_name,
-                          CUR.face->root.style_name ));
+                          exc->face->root.family_name,
+                          exc->face->root.style_name ));
 
               switch ( i )
               {
@@ -8372,17 +7704,11 @@
         }
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
-        FT_Long*  args   = CUR.stack + CUR.args;
-        FT_Byte   opcode = CUR.opcode;
-
-
-#undef  ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
+        FT_Long*  args   = exc->stack + exc->args;
+        FT_Byte   opcode = exc->opcode;
 
 
         switch ( opcode )
@@ -8393,580 +7719,566 @@
         case 0x03:  /* SPvTCA x */
         case 0x04:  /* SFvTCA y */
         case 0x05:  /* SFvTCA x */
-          {
-            FT_Short  AA, BB;
-
-
-            AA = (FT_Short)( ( opcode & 1 ) << 14 );
-            BB = (FT_Short)( AA ^ 0x4000 );
-
-            if ( opcode < 4 )
-            {
-              CUR.GS.projVector.x = AA;
-              CUR.GS.projVector.y = BB;
-
-              CUR.GS.dualVector.x = AA;
-              CUR.GS.dualVector.y = BB;
-            }
-            else
-            {
-              GUESS_VECTOR( projVector );
-            }
-
-            if ( ( opcode & 2 ) == 0 )
-            {
-              CUR.GS.freeVector.x = AA;
-              CUR.GS.freeVector.y = BB;
-            }
-            else
-            {
-              GUESS_VECTOR( freeVector );
-            }
-
-            COMPUTE_Funcs();
-          }
+          Ins_SxyTCA( exc );
           break;
 
         case 0x06:  /* SPvTL // */
         case 0x07:  /* SPvTL +  */
-          DO_SPVTL
+          Ins_SPVTL( exc, args );
           break;
 
         case 0x08:  /* SFvTL // */
         case 0x09:  /* SFvTL +  */
-          DO_SFVTL
+          Ins_SFVTL( exc, args );
           break;
 
         case 0x0A:  /* SPvFS */
-          DO_SPVFS
+          Ins_SPVFS( exc, args );
           break;
 
         case 0x0B:  /* SFvFS */
-          DO_SFVFS
+          Ins_SFVFS( exc, args );
           break;
 
-        case 0x0C:  /* GPV */
-          DO_GPV
+        case 0x0C:  /* GPv */
+          Ins_GPV( exc, args );
           break;
 
-        case 0x0D:  /* GFV */
-          DO_GFV
+        case 0x0D:  /* GFv */
+          Ins_GFV( exc, args );
           break;
 
         case 0x0E:  /* SFvTPv */
-          DO_SFVTPV
+          Ins_SFVTPV( exc );
           break;
 
         case 0x0F:  /* ISECT  */
-          Ins_ISECT( EXEC_ARG_ args );
+          Ins_ISECT( exc, args );
           break;
 
         case 0x10:  /* SRP0 */
-          DO_SRP0
+          Ins_SRP0( exc, args );
           break;
 
         case 0x11:  /* SRP1 */
-          DO_SRP1
+          Ins_SRP1( exc, args );
           break;
 
         case 0x12:  /* SRP2 */
-          DO_SRP2
+          Ins_SRP2( exc, args );
           break;
 
         case 0x13:  /* SZP0 */
-          Ins_SZP0( EXEC_ARG_ args );
+          Ins_SZP0( exc, args );
           break;
 
         case 0x14:  /* SZP1 */
-          Ins_SZP1( EXEC_ARG_ args );
+          Ins_SZP1( exc, args );
           break;
 
         case 0x15:  /* SZP2 */
-          Ins_SZP2( EXEC_ARG_ args );
+          Ins_SZP2( exc, args );
           break;
 
         case 0x16:  /* SZPS */
-          Ins_SZPS( EXEC_ARG_ args );
+          Ins_SZPS( exc, args );
           break;
 
         case 0x17:  /* SLOOP */
-          DO_SLOOP
+          Ins_SLOOP( exc, args );
           break;
 
         case 0x18:  /* RTG */
-          DO_RTG
+          Ins_RTG( exc );
           break;
 
         case 0x19:  /* RTHG */
-          DO_RTHG
+          Ins_RTHG( exc );
           break;
 
         case 0x1A:  /* SMD */
-          DO_SMD
+          Ins_SMD( exc, args );
           break;
 
         case 0x1B:  /* ELSE */
-          Ins_ELSE( EXEC_ARG_ args );
+          Ins_ELSE( exc );
           break;
 
         case 0x1C:  /* JMPR */
-          DO_JMPR
+          Ins_JMPR( exc, args );
           break;
 
         case 0x1D:  /* SCVTCI */
-          DO_SCVTCI
+          Ins_SCVTCI( exc, args );
           break;
 
         case 0x1E:  /* SSWCI */
-          DO_SSWCI
+          Ins_SSWCI( exc, args );
           break;
 
         case 0x1F:  /* SSW */
-          DO_SSW
+          Ins_SSW( exc, args );
           break;
 
         case 0x20:  /* DUP */
-          DO_DUP
+          Ins_DUP( args );
           break;
 
         case 0x21:  /* POP */
-          /* nothing :-) */
+          Ins_POP();
           break;
 
         case 0x22:  /* CLEAR */
-          DO_CLEAR
+          Ins_CLEAR( exc );
           break;
 
         case 0x23:  /* SWAP */
-          DO_SWAP
+          Ins_SWAP( args );
           break;
 
         case 0x24:  /* DEPTH */
-          DO_DEPTH
+          Ins_DEPTH( exc, args );
           break;
 
         case 0x25:  /* CINDEX */
-          DO_CINDEX
+          Ins_CINDEX( exc, args );
           break;
 
         case 0x26:  /* MINDEX */
-          Ins_MINDEX( EXEC_ARG_ args );
+          Ins_MINDEX( exc, args );
           break;
 
         case 0x27:  /* ALIGNPTS */
-          Ins_ALIGNPTS( EXEC_ARG_ args );
+          Ins_ALIGNPTS( exc, args );
           break;
 
-        case 0x28:  /* ???? */
-          Ins_UNKNOWN( EXEC_ARG_ args );
+        case 0x28:  /* RAW */
+          Ins_UNKNOWN( exc );
           break;
 
         case 0x29:  /* UTP */
-          Ins_UTP( EXEC_ARG_ args );
+          Ins_UTP( exc, args );
           break;
 
         case 0x2A:  /* LOOPCALL */
-          Ins_LOOPCALL( EXEC_ARG_ args );
+          Ins_LOOPCALL( exc, args );
           break;
 
         case 0x2B:  /* CALL */
-          Ins_CALL( EXEC_ARG_ args );
+          Ins_CALL( exc, args );
           break;
 
         case 0x2C:  /* FDEF */
-          Ins_FDEF( EXEC_ARG_ args );
+          Ins_FDEF( exc, args );
           break;
 
         case 0x2D:  /* ENDF */
-          Ins_ENDF( EXEC_ARG_ args );
+          Ins_ENDF( exc );
           break;
 
         case 0x2E:  /* MDAP */
         case 0x2F:  /* MDAP */
-          Ins_MDAP( EXEC_ARG_ args );
+          Ins_MDAP( exc, args );
           break;
 
         case 0x30:  /* IUP */
         case 0x31:  /* IUP */
-          Ins_IUP( EXEC_ARG_ args );
+          Ins_IUP( exc );
           break;
 
         case 0x32:  /* SHP */
         case 0x33:  /* SHP */
-          Ins_SHP( EXEC_ARG_ args );
+          Ins_SHP( exc );
           break;
 
         case 0x34:  /* SHC */
         case 0x35:  /* SHC */
-          Ins_SHC( EXEC_ARG_ args );
+          Ins_SHC( exc, args );
           break;
 
         case 0x36:  /* SHZ */
         case 0x37:  /* SHZ */
-          Ins_SHZ( EXEC_ARG_ args );
+          Ins_SHZ( exc, args );
           break;
 
         case 0x38:  /* SHPIX */
-          Ins_SHPIX( EXEC_ARG_ args );
+          Ins_SHPIX( exc, args );
           break;
 
         case 0x39:  /* IP    */
-          Ins_IP( EXEC_ARG_ args );
+          Ins_IP( exc );
           break;
 
         case 0x3A:  /* MSIRP */
         case 0x3B:  /* MSIRP */
-          Ins_MSIRP( EXEC_ARG_ args );
+          Ins_MSIRP( exc, args );
           break;
 
         case 0x3C:  /* AlignRP */
-          Ins_ALIGNRP( EXEC_ARG_ args );
+          Ins_ALIGNRP( exc );
           break;
 
         case 0x3D:  /* RTDG */
-          DO_RTDG
+          Ins_RTDG( exc );
           break;
 
         case 0x3E:  /* MIAP */
         case 0x3F:  /* MIAP */
-          Ins_MIAP( EXEC_ARG_ args );
+          Ins_MIAP( exc, args );
           break;
 
         case 0x40:  /* NPUSHB */
-          Ins_NPUSHB( EXEC_ARG_ args );
+          Ins_NPUSHB( exc, args );
           break;
 
         case 0x41:  /* NPUSHW */
-          Ins_NPUSHW( EXEC_ARG_ args );
+          Ins_NPUSHW( exc, args );
           break;
 
         case 0x42:  /* WS */
-          DO_WS
-          break;
-
-      Set_Invalid_Ref:
-            CUR.error = FT_THROW( Invalid_Reference );
+          Ins_WS( exc, args );
           break;
 
         case 0x43:  /* RS */
-          DO_RS
+          Ins_RS( exc, args );
           break;
 
         case 0x44:  /* WCVTP */
-          DO_WCVTP
+          Ins_WCVTP( exc, args );
           break;
 
         case 0x45:  /* RCVT */
-          DO_RCVT
+          Ins_RCVT( exc, args );
           break;
 
         case 0x46:  /* GC */
         case 0x47:  /* GC */
-          Ins_GC( EXEC_ARG_ args );
+          Ins_GC( exc, args );
           break;
 
         case 0x48:  /* SCFS */
-          Ins_SCFS( EXEC_ARG_ args );
+          Ins_SCFS( exc, args );
           break;
 
         case 0x49:  /* MD */
         case 0x4A:  /* MD */
-          Ins_MD( EXEC_ARG_ args );
+          Ins_MD( exc, args );
           break;
 
         case 0x4B:  /* MPPEM */
-          DO_MPPEM
+          Ins_MPPEM( exc, args );
           break;
 
         case 0x4C:  /* MPS */
-          DO_MPS
+          Ins_MPS( exc, args );
           break;
 
         case 0x4D:  /* FLIPON */
-          DO_FLIPON
+          Ins_FLIPON( exc );
           break;
 
         case 0x4E:  /* FLIPOFF */
-          DO_FLIPOFF
+          Ins_FLIPOFF( exc );
           break;
 
         case 0x4F:  /* DEBUG */
-          DO_DEBUG
+          Ins_DEBUG( exc );
           break;
 
         case 0x50:  /* LT */
-          DO_LT
+          Ins_LT( args );
           break;
 
         case 0x51:  /* LTEQ */
-          DO_LTEQ
+          Ins_LTEQ( args );
           break;
 
         case 0x52:  /* GT */
-          DO_GT
+          Ins_GT( args );
           break;
 
         case 0x53:  /* GTEQ */
-          DO_GTEQ
+          Ins_GTEQ( args );
           break;
 
         case 0x54:  /* EQ */
-          DO_EQ
+          Ins_EQ( args );
           break;
 
         case 0x55:  /* NEQ */
-          DO_NEQ
+          Ins_NEQ( args );
           break;
 
         case 0x56:  /* ODD */
-          DO_ODD
+          Ins_ODD( exc, args );
           break;
 
         case 0x57:  /* EVEN */
-          DO_EVEN
+          Ins_EVEN( exc, args );
           break;
 
         case 0x58:  /* IF */
-          Ins_IF( EXEC_ARG_ args );
+          Ins_IF( exc, args );
           break;
 
         case 0x59:  /* EIF */
-          /* do nothing */
+          Ins_EIF();
           break;
 
         case 0x5A:  /* AND */
-          DO_AND
+          Ins_AND( args );
           break;
 
         case 0x5B:  /* OR */
-          DO_OR
+          Ins_OR( args );
           break;
 
         case 0x5C:  /* NOT */
-          DO_NOT
+          Ins_NOT( args );
           break;
 
         case 0x5D:  /* DELTAP1 */
-          Ins_DELTAP( EXEC_ARG_ args );
+          Ins_DELTAP( exc, args );
           break;
 
         case 0x5E:  /* SDB */
-          DO_SDB
+          Ins_SDB( exc, args );
           break;
 
         case 0x5F:  /* SDS */
-          DO_SDS
+          Ins_SDS( exc, args );
           break;
 
         case 0x60:  /* ADD */
-          DO_ADD
+          Ins_ADD( args );
           break;
 
         case 0x61:  /* SUB */
-          DO_SUB
+          Ins_SUB( args );
           break;
 
         case 0x62:  /* DIV */
-          DO_DIV
+          Ins_DIV( exc, args );
           break;
 
         case 0x63:  /* MUL */
-          DO_MUL
+          Ins_MUL( args );
           break;
 
         case 0x64:  /* ABS */
-          DO_ABS
+          Ins_ABS( args );
           break;
 
         case 0x65:  /* NEG */
-          DO_NEG
+          Ins_NEG( args );
           break;
 
         case 0x66:  /* FLOOR */
-          DO_FLOOR
+          Ins_FLOOR( args );
           break;
 
         case 0x67:  /* CEILING */
-          DO_CEILING
+          Ins_CEILING( args );
           break;
 
         case 0x68:  /* ROUND */
         case 0x69:  /* ROUND */
         case 0x6A:  /* ROUND */
         case 0x6B:  /* ROUND */
-          DO_ROUND
+          Ins_ROUND( exc, args );
           break;
 
         case 0x6C:  /* NROUND */
         case 0x6D:  /* NROUND */
         case 0x6E:  /* NRRUND */
         case 0x6F:  /* NROUND */
-          DO_NROUND
+          Ins_NROUND( exc, args );
           break;
 
         case 0x70:  /* WCVTF */
-          DO_WCVTF
+          Ins_WCVTF( exc, args );
           break;
 
         case 0x71:  /* DELTAP2 */
         case 0x72:  /* DELTAP3 */
-          Ins_DELTAP( EXEC_ARG_ args );
+          Ins_DELTAP( exc, args );
           break;
 
         case 0x73:  /* DELTAC0 */
         case 0x74:  /* DELTAC1 */
         case 0x75:  /* DELTAC2 */
-          Ins_DELTAC( EXEC_ARG_ args );
+          Ins_DELTAC( exc, args );
           break;
 
         case 0x76:  /* SROUND */
-          DO_SROUND
+          Ins_SROUND( exc, args );
           break;
 
         case 0x77:  /* S45Round */
-          DO_S45ROUND
+          Ins_S45ROUND( exc, args );
           break;
 
         case 0x78:  /* JROT */
-          DO_JROT
+          Ins_JROT( exc, args );
           break;
 
         case 0x79:  /* JROF */
-          DO_JROF
+          Ins_JROF( exc, args );
           break;
 
         case 0x7A:  /* ROFF */
-          DO_ROFF
+          Ins_ROFF( exc );
           break;
 
         case 0x7B:  /* ???? */
-          Ins_UNKNOWN( EXEC_ARG_ args );
+          Ins_UNKNOWN( exc );
           break;
 
         case 0x7C:  /* RUTG */
-          DO_RUTG
+          Ins_RUTG( exc );
           break;
 
         case 0x7D:  /* RDTG */
-          DO_RDTG
+          Ins_RDTG( exc );
           break;
 
         case 0x7E:  /* SANGW */
-        case 0x7F:  /* AA    */
-          /* nothing - obsolete */
+          Ins_SANGW();
+          break;
+
+        case 0x7F:  /* AA */
+          Ins_AA();
           break;
 
         case 0x80:  /* FLIPPT */
-          Ins_FLIPPT( EXEC_ARG_ args );
+          Ins_FLIPPT( exc );
           break;
 
         case 0x81:  /* FLIPRGON */
-          Ins_FLIPRGON( EXEC_ARG_ args );
+          Ins_FLIPRGON( exc, args );
           break;
 
         case 0x82:  /* FLIPRGOFF */
-          Ins_FLIPRGOFF( EXEC_ARG_ args );
+          Ins_FLIPRGOFF( exc, args );
           break;
 
         case 0x83:  /* UNKNOWN */
         case 0x84:  /* UNKNOWN */
-          Ins_UNKNOWN( EXEC_ARG_ args );
+          Ins_UNKNOWN( exc );
           break;
 
         case 0x85:  /* SCANCTRL */
-          Ins_SCANCTRL( EXEC_ARG_ args );
+          Ins_SCANCTRL( exc, args );
           break;
 
-        case 0x86:  /* SDPVTL */
-        case 0x87:  /* SDPVTL */
-          Ins_SDPVTL( EXEC_ARG_ args );
+        case 0x86:  /* SDPvTL */
+        case 0x87:  /* SDPvTL */
+          Ins_SDPVTL( exc, args );
           break;
 
         case 0x88:  /* GETINFO */
-          Ins_GETINFO( EXEC_ARG_ args );
+          Ins_GETINFO( exc, args );
           break;
 
         case 0x89:  /* IDEF */
-          Ins_IDEF( EXEC_ARG_ args );
+          Ins_IDEF( exc, args );
           break;
 
         case 0x8A:  /* ROLL */
-          Ins_ROLL( EXEC_ARG_ args );
+          Ins_ROLL( args );
           break;
 
         case 0x8B:  /* MAX */
-          DO_MAX
+          Ins_MAX( args );
           break;
 
         case 0x8C:  /* MIN */
-          DO_MIN
+          Ins_MIN( args );
           break;
 
         case 0x8D:  /* SCANTYPE */
-          Ins_SCANTYPE( EXEC_ARG_ args );
+          Ins_SCANTYPE( exc, args );
           break;
 
         case 0x8E:  /* INSTCTRL */
-          Ins_INSTCTRL( EXEC_ARG_ args );
+          Ins_INSTCTRL( exc, args );
           break;
 
-        case 0x8F:
-          Ins_UNKNOWN( EXEC_ARG_ args );
+        case 0x8F:  /* ADJUST */
+        case 0x90:  /* ADJUST */
+          Ins_UNKNOWN( exc );
           break;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+        case 0x91:
+          /* it is the job of the application to `activate' GX handling, */
+          /* this is, calling any of the GX API functions on the current */
+          /* font to select a variation instance                         */
+          if ( exc->face->blend )
+            Ins_GETVARIATION( exc, args );
+          else
+            Ins_UNKNOWN( exc );
+          break;
+
+        case 0x92:
+          /* there is at least one MS font (LaoUI.ttf version 5.01) that */
+          /* uses IDEFs for 0x91 and 0x92; for this reason we activate   */
+          /* GETDATA for GX fonts only, similar to GETVARIATION          */
+          if ( exc->face->blend )
+            Ins_GETDATA( args );
+          else
+            Ins_UNKNOWN( exc );
+          break;
+#endif
+
         default:
           if ( opcode >= 0xE0 )
-            Ins_MIRP( EXEC_ARG_ args );
+            Ins_MIRP( exc, args );
           else if ( opcode >= 0xC0 )
-            Ins_MDRP( EXEC_ARG_ args );
+            Ins_MDRP( exc, args );
           else if ( opcode >= 0xB8 )
-            Ins_PUSHW( EXEC_ARG_ args );
+            Ins_PUSHW( exc, args );
           else if ( opcode >= 0xB0 )
-            Ins_PUSHB( EXEC_ARG_ args );
+            Ins_PUSHB( exc, args );
           else
-            Ins_UNKNOWN( EXEC_ARG_ args );
+            Ins_UNKNOWN( exc );
         }
-
       }
 
-#else
-
-      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
-
-#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-      if ( CUR.error )
+      if ( exc->error )
       {
-        switch ( CUR.error )
+        switch ( exc->error )
         {
           /* looking for redefined instructions */
         case FT_ERR( Invalid_Opcode ):
           {
-            TT_DefRecord*  def   = CUR.IDefs;
-            TT_DefRecord*  limit = def + CUR.numIDefs;
+            TT_DefRecord*  def   = exc->IDefs;
+            TT_DefRecord*  limit = def + exc->numIDefs;
 
 
             for ( ; def < limit; def++ )
             {
-              if ( def->active && CUR.opcode == (FT_Byte)def->opc )
+              if ( def->active && exc->opcode == (FT_Byte)def->opc )
               {
                 TT_CallRec*  callrec;
 
 
-                if ( CUR.callTop >= CUR.callSize )
+                if ( exc->callTop >= exc->callSize )
                 {
-                  CUR.error = FT_THROW( Invalid_Reference );
+                  exc->error = FT_THROW( Invalid_Reference );
                   goto LErrorLabel_;
                 }
 
-                callrec = &CUR.callStack[CUR.callTop];
+                callrec = &exc->callStack[exc->callTop];
 
-                callrec->Caller_Range = CUR.curRange;
-                callrec->Caller_IP    = CUR.IP + 1;
+                callrec->Caller_Range = exc->curRange;
+                callrec->Caller_IP    = exc->IP + 1;
                 callrec->Cur_Count    = 1;
                 callrec->Def          = def;
 
-                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+                if ( Ins_Goto_CodeRange( exc,
+                                         def->range,
+                                         def->start ) == FAILURE )
                   goto LErrorLabel_;
 
                 goto LSuiteLabel_;
@@ -8974,7 +8286,7 @@
             }
           }
 
-          CUR.error = FT_THROW( Invalid_Opcode );
+          exc->error = FT_THROW( Invalid_Opcode );
           goto LErrorLabel_;
 
 #if 0
@@ -8992,59 +8304,49 @@
         }
       }
 
-      CUR.top = CUR.new_top;
+      exc->top = exc->new_top;
 
-      if ( CUR.step_ins )
-        CUR.IP += CUR.length;
+      if ( exc->step_ins )
+        exc->IP += exc->length;
 
       /* increment instruction counter and check if we didn't */
       /* run this program for too long (e.g. infinite loops). */
-      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+      if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
         return FT_THROW( Execution_Too_Long );
 
     LSuiteLabel_:
-      if ( CUR.IP >= CUR.codeSize )
+      if ( exc->IP >= exc->codeSize )
       {
-        if ( CUR.callTop > 0 )
+        if ( exc->callTop > 0 )
         {
-          CUR.error = FT_THROW( Code_Overflow );
+          exc->error = FT_THROW( Code_Overflow );
           goto LErrorLabel_;
         }
         else
           goto LNo_Error_;
       }
-    } while ( !CUR.instruction_trap );
+    } while ( !exc->instruction_trap );
 
   LNo_Error_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    *exc = cur;
-#endif
-
     return FT_Err_Ok;
 
   LErrorCodeOverflow_:
-    CUR.error = FT_THROW( Code_Overflow );
+    exc->error = FT_THROW( Code_Overflow );
 
   LErrorLabel_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    *exc = cur;
-#endif
-
     /* If any errors have occurred, function tables may be broken. */
     /* Force a re-execution of `prep' and `fpgm' tables if no      */
     /* bytecode debugger is run.                                   */
-    if ( CUR.error
-         && !CUR.instruction_trap
-         && CUR.curRange == tt_coderange_glyph )
+    if ( exc->error                          &&
+         !exc->instruction_trap              &&
+         exc->curRange == tt_coderange_glyph )
     {
-      FT_TRACE1(( "  The interpreter returned error 0x%x\n", CUR.error ));
+      FT_TRACE1(( "  The interpreter returned error 0x%x\n", exc->error ));
       exc->size->bytecode_ready = -1;
       exc->size->cvt_ready      = -1;
     }
 
-    return CUR.error;
+    return exc->error;
   }
 
 
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 1d8825d..53f0944 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (specification).                       */
 /*                                                                         */
-/*  Copyright 1996-2007, 2010, 2012-2013 by                                */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTINTERP_H__
-#define __TTINTERP_H__
+#ifndef TTINTERP_H_
+#define TTINTERP_H_
 
 #include <ft2build.h>
 #include "ttobjs.h"
@@ -26,23 +26,6 @@
 FT_BEGIN_HEADER
 
 
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
-
-#define EXEC_OP_   TT_ExecContext  exc,
-#define EXEC_OP    TT_ExecContext  exc
-#define EXEC_ARG_  exc,
-#define EXEC_ARG   exc
-
-#else                                       /* static implementation */
-
-#define EXEC_OP_   /* void */
-#define EXEC_OP    /* void */
-#define EXEC_ARG_  /* void */
-#define EXEC_ARG   /* void */
-
-#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* Rounding mode constants.                                              */
@@ -67,29 +50,38 @@
 
   /* Rounding function */
   typedef FT_F26Dot6
-  (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6  distance,
-                             FT_F26Dot6  compensation );
+  (*TT_Round_Func)( TT_ExecContext  exc,
+                    FT_F26Dot6      distance,
+                    FT_F26Dot6      compensation );
 
   /* Point displacement along the freedom vector routine */
   typedef void
-  (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone  zone,
-                            FT_UShort     point,
-                            FT_F26Dot6    distance );
+  (*TT_Move_Func)( TT_ExecContext  exc,
+                   TT_GlyphZone    zone,
+                   FT_UShort       point,
+                   FT_F26Dot6      distance );
 
   /* Distance projection along one of the projection vectors */
   typedef FT_F26Dot6
-  (*TT_Project_Func)( EXEC_OP_ FT_Pos   dx,
-                               FT_Pos   dy );
+  (*TT_Project_Func)( TT_ExecContext  exc,
+                      FT_Pos          dx,
+                      FT_Pos          dy );
+
+  /* getting current ppem.  Take care of non-square pixels if necessary */
+  typedef FT_Long
+  (*TT_Cur_Ppem_Func)( TT_ExecContext  exc );
 
   /* reading a cvt value.  Take care of non-square pixels if necessary */
   typedef FT_F26Dot6
-  (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong  idx );
+  (*TT_Get_CVT_Func)( TT_ExecContext  exc,
+                      FT_ULong        idx );
 
   /* setting or moving a cvt value.  Take care of non-square pixels  */
   /* if necessary                                                    */
   typedef void
-  (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong    idx,
-                               FT_F26Dot6  value );
+  (*TT_Set_CVT_Func)( TT_ExecContext  exc,
+                      FT_ULong        idx,
+                      FT_F26Dot6      value );
 
 
   /*************************************************************************/
@@ -107,7 +99,7 @@
   } TT_CallRec, *TT_CallStack;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -146,7 +138,7 @@
 
   } SPH_Font_Class;
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
   /*************************************************************************/
@@ -166,11 +158,11 @@
 
     FT_Long            top;        /* top of exec. stack   */
 
-    FT_UInt            stackSize;  /* size of exec. stack  */
+    FT_Long            stackSize;  /* size of exec. stack  */
     FT_Long*           stack;      /* current exec. stack  */
 
     FT_Long            args;
-    FT_UInt            new_top;    /* new top after exec.  */
+    FT_Long            new_top;    /* new top after exec.  */
 
     TT_GlyphZoneRec    zp0,        /* zone records */
                        zp1,
@@ -178,6 +170,7 @@
                        pts,
                        twilight;
 
+    FT_Long            pointSize;  /* in 26.6 format */
     FT_Size_Metrics    metrics;
     TT_Size_Metrics    tt_metrics; /* size metrics */
 
@@ -228,11 +221,6 @@
     FT_F26Dot6         phase;      /* `SuperRounding'     */
     FT_F26Dot6         threshold;
 
-#if 0
-    /* this seems to be unused */
-    FT_Int             cur_ppem;   /* ppem along the current proj vector */
-#endif
-
     FT_Bool            instruction_trap; /* If `True', the interpreter will */
                                          /* exit after each instruction     */
 
@@ -254,27 +242,159 @@
     TT_Move_Func       func_move;      /* current point move function */
     TT_Move_Func       func_move_orig; /* move original position function */
 
+    TT_Cur_Ppem_Func   func_cur_ppem;  /* get current proj. ppem value  */
+
     TT_Get_CVT_Func    func_read_cvt;  /* read a cvt entry              */
     TT_Set_CVT_Func    func_write_cvt; /* write a cvt entry (in pixels) */
     TT_Set_CVT_Func    func_move_cvt;  /* incr a cvt entry (in pixels)  */
 
-    FT_Bool            grayscale;      /* are we hinting for grayscale? */
+    FT_Bool            grayscale;      /* bi-level hinting and */
+                                       /* grayscale rendering  */
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /*
+     * Modern TrueType fonts are usually rendered through Microsoft's
+     * collection of rendering techniques called ClearType (e.g., subpixel
+     * rendering and subpixel hinting).  When ClearType was introduced, most
+     * fonts were not ready.  Microsoft decided to implement a backwards
+     * compatibility mode that employed several simple to complicated
+     * assumptions and tricks that modified the interpretation of the
+     * bytecode contained in these fonts to make them look ClearType-y
+     * somehow.  Most (web)fonts that were released since then have come to
+     * rely on these hacks to render correctly, even some of Microsoft's
+     * flagship ClearType fonts (Calibri, Cambria, Segoe UI).
+     *
+     * The minimal subpixel hinting code (interpreter version 40) employs a
+     * small list of font-agnostic hacks to bludgeon non-native-ClearType
+     * fonts (except tricky ones[1]) into submission.  It will not try to
+     * toggle hacks for specific fonts for performance and complexity
+     * reasons.  The focus is on modern (web)fonts rather than legacy fonts
+     * that were made for black-and-white rendering.
+     *
+     * Major hacks
+     *
+     * - Any point movement on the x axis is ignored (cf. `Direct_Move' and
+     *   `Direct_Move_X').  This has the smallest code footprint and single
+     *   biggest effect.  The ClearType way to increase resolution is
+     *   supersampling the x axis, the FreeType way is ignoring instructions
+     *   on the x axis, which gives the same result in the majority of
+     *   cases.
+     *
+     * - Points are not moved post-IUP (neither on the x nor on the y axis),
+     *   except the x component of diagonal moves post-IUP (cf.
+     *   `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point').  Post-IUP
+     *   changes are commonly used to `fix' pixel patterns which has little
+     *   use outside monochrome rendering.
+     *
+     * - SHPIX and DELTAP don't execute unless moving a composite on the
+     *   y axis or moving a previously y touched point.  SHPIX additionally
+     *   denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP').
+     *   Both instructions are commonly used to `fix' pixel patterns for
+     *   monochrome or Windows's GDI rendering but make little sense for
+     *   FreeType rendering.  Both can distort the outline.  See [2] for
+     *   details.
+     *
+     * - The hdmx table and modifications to phantom points are ignored.
+     *   Bearings and advance widths remain unchanged (except rounding them
+     *   outside the interpreter!), cf. `compute_glyph_metrics' and
+     *   `TT_Hint_Glyph'.  Letting non-native-ClearType fonts modify spacing
+     *   might mess up spacing.
+     *
+     * Minor hacks
+     *
+     * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP.  This
+     *   prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
+     *   various sizes.
+     *
+     * (Post-IUP is the state after both IUP[x] and IUP[y] have been
+     * executed.)
+     *
+     * The best results are achieved for fonts that were from the outset
+     * designed with ClearType in mind, meaning they leave the x axis mostly
+     * alone and don't mess with the `final' outline to produce more
+     * pleasing pixel patterns.  The harder the designer tried to produce
+     * very specific patterns (`superhinting') for pre-ClearType-displays,
+     * the worse the results.
+     *
+     * Microsoft defines a way to turn off backwards compatibility and
+     * interpret instructions as before (called `native ClearType')[2][3].
+     * The font designer then regains full control and is responsible for
+     * making the font work correctly with ClearType without any
+     * hand-holding by the interpreter or rasterizer[4].  The v40
+     * interpreter assumes backwards compatibility by default, which can be
+     * turned off the same way by executing the following in the control
+     * program (cf. `Ins_INSTCTRL').
+     *
+     *   #PUSH 4,3
+     *   INSTCTRL[]
+     *
+     * [1] Tricky fonts as FreeType defines them rely on the bytecode
+     *     interpreter to display correctly.  Hacks can interfere with them,
+     *     so they get treated like native ClearType fonts (v40 with
+     *     backwards compatibility turned off).  Cf. `TT_RunIns'.
+     *
+     * [2] Proposed by Microsoft's Greg Hitchcock in
+     *     https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+     *
+     * [3] Beat Stamm describes it in more detail:
+     *     http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
+     *
+     * [4] The list of `native ClearType' fonts is small at the time of this
+     *     writing; I found the following on a Windows 10 Update 1511
+     *     installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
+     *     JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
+     *     SimSun, NSimSun, and Yu Gothic.
+     *
+     */
+
+    /* Using v40 implies subpixel hinting.  Used to detect interpreter */
+    /* version switches.  `_lean' to differentiate from the Infinality */
+    /* `subpixel_hinting', which is managed differently.               */
+    FT_Bool            subpixel_hinting_lean;
+
+    /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
+    /* `_lean' to differentiate from the Infinality `vertical_lcd', which */
+    /* is managed differently.                                            */
+    FT_Bool            vertical_lcd_lean;
+
+    /* Default to backwards compatibility mode in v40 interpreter.  If  */
+    /* this is false, it implies the interpreter is in v35 or in native */
+    /* ClearType mode.                                                  */
+    FT_Bool            backwards_compatibility;
+
+    /* Useful for detecting and denying post-IUP trickery that is usually */
+    /* used to fix pixel patterns (`superhinting').                       */
+    FT_Bool            iupx_called;
+    FT_Bool            iupy_called;
+
+    /* ClearType hinting and grayscale rendering, as used by Universal */
+    /* Windows Platform apps (Windows 8 and above).  Like the standard */
+    /* colorful ClearType mode, it utilizes a vastly increased virtual */
+    /* resolution on the x axis.  Different from bi-level hinting and  */
+    /* grayscale rendering, the old mode from Win9x days that roughly  */
+    /* adheres to the physical pixel grid on both axes.                */
+    FT_Bool            grayscale_cleartype;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
 
-    FT_Bool            subpixel;          /* Using subpixel hinting?       */
+    FT_Bool            subpixel_hinting;  /* Using subpixel hinting?       */
     FT_Bool            ignore_x_mode;     /* Standard rendering mode for   */
                                           /* subpixel hinting.  On if gray */
                                           /* or subpixel hinting is on.    */
 
-    /* The following 4 aren't fully implemented but here for MS rasterizer */
+    /* The following 6 aren't fully implemented but here for MS rasterizer */
     /* compatibility.                                                      */
     FT_Bool            compatible_widths;     /* compatible widths?        */
     FT_Bool            symmetrical_smoothing; /* symmetrical_smoothing?    */
     FT_Bool            bgr;                   /* bgr instead of rgb?       */
+    FT_Bool            vertical_lcd;          /* long side of LCD subpixel */
+                                              /* rectangles is horizontal  */
     FT_Bool            subpixel_positioned;   /* subpixel positioned       */
                                               /* (DirectWrite ClearType)?  */
+    FT_Bool            gray_cleartype;        /* ClearType hinting but     */
+                                              /* grayscale rendering       */
 
     FT_Int             rasterizer_version;    /* MS rasterizer version     */
 
@@ -286,7 +406,7 @@
     FT_ULong           sph_in_func_flags;     /* flags to indicate if in   */
                                               /* special functions         */
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   } TT_ExecContextRec;
 
@@ -295,18 +415,18 @@
 
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   TT_Goto_CodeRange( TT_ExecContext  exec,
                      FT_Int          range,
                      FT_Long         IP );
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   TT_Set_CodeRange( TT_ExecContext  exec,
                     FT_Int          range,
                     void*           base,
                     FT_Long         length );
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   TT_Clear_CodeRange( TT_ExecContext  exec,
                       FT_Int          range );
 
@@ -314,7 +434,7 @@
   FT_LOCAL( FT_Error )
   Update_Max( FT_Memory  memory,
               FT_ULong*  size,
-              FT_Long    multiplier,
+              FT_ULong   multiplier,
               void*      _pbuff,
               FT_ULong   new_max );
 #endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -338,13 +458,14 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    Only the glyph loader and debugger should call this function.      */
+  /*    (And right now only the glyph loader uses it.)                     */
   /*                                                                       */
   FT_EXPORT( TT_ExecContext )
   TT_New_Context( TT_Driver  driver );
 
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   TT_Done_Context( TT_ExecContext  exec );
 
   FT_LOCAL( FT_Error )
@@ -352,13 +473,12 @@
                    TT_Face         face,
                    TT_Size         size );
 
-  FT_LOCAL( FT_Error )
+  FT_LOCAL( void )
   TT_Save_Context( TT_ExecContext  exec,
                    TT_Size         ins );
 
   FT_LOCAL( FT_Error )
-  TT_Run_Context( TT_ExecContext  exec,
-                  FT_Bool         debug );
+  TT_Run_Context( TT_ExecContext  exec );
 #endif /* TT_USE_BYTECODE_INTERPRETER */
 
 
@@ -389,7 +509,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTINTERP_H__ */
+#endif /* TTINTERP_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 05a121c..ed3be2d 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (body).                                              */
 /*                                                                         */
-/*  Copyright 1996-2013                                                    */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -32,10 +32,6 @@
 #include "ttinterp.h"
 #endif
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#include FT_TRUETYPE_UNPATENTED_H
-#endif
-
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include "ttgxvar.h"
 #endif
@@ -191,7 +187,7 @@
   {
     FT_Error   error;
     FT_UInt32  checksum = 0;
-    int        i;
+    FT_UInt    i;
 
 
     if ( FT_FRAME_ENTER( length ) )
@@ -200,8 +196,8 @@
     for ( ; length > 3; length -= 4 )
       checksum += (FT_UInt32)FT_GET_ULONG();
 
-    for ( i = 3; length > 0; length --, i-- )
-      checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
+    for ( i = 3; length > 0; length--, i-- )
+      checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
 
     FT_FRAME_EXIT();
 
@@ -246,7 +242,7 @@
   tt_check_trickyness_sfnt_ids( TT_Face  face )
   {
 #define TRICK_SFNT_IDS_PER_FACE   3
-#define TRICK_SFNT_IDS_NUM_FACES  17
+#define TRICK_SFNT_IDS_NUM_FACES  18
 
     static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
                                        [TRICK_SFNT_IDS_PER_FACE] = {
@@ -256,89 +252,94 @@
 #define TRICK_SFNT_ID_prep  2
 
       { /* MingLiU 1995 */
-        { 0x05bcf058, 0x000002e4 }, /* cvt  */
-        { 0x28233bf1, 0x000087c4 }, /* fpgm */
-        { 0xa344a1ea, 0x000001e1 }  /* prep */
+        { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
+        { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
+        { 0xA344A1EAUL, 0x000001E1UL }  /* prep */
       },
       { /* MingLiU 1996- */
-        { 0x05bcf058, 0x000002e4 }, /* cvt  */
-        { 0x28233bf1, 0x000087c4 }, /* fpgm */
-        { 0xa344a1eb, 0x000001e1 }  /* prep */
+        { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
+        { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
+        { 0xA344A1EBUL, 0x000001E1UL }  /* prep */
       },
       { /* DFKaiShu */
-        { 0x11e5ead4, 0x00000350 }, /* cvt  */
-        { 0x5a30ca3b, 0x00009063 }, /* fpgm */
-        { 0x13a42602, 0x0000007e }  /* prep */
+        { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
+        { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
+        { 0x13A42602UL, 0x0000007EUL }  /* prep */
+      },
+      { /* DFKaiShu2 */
+        { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
+        { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
+        { 0x13A42602UL, 0x0000007EUL }  /* prep */
       },
       { /* HuaTianKaiTi */
-        { 0xfffbfffc, 0x00000008 }, /* cvt  */
-        { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
-        { 0x70020112, 0x00000008 }  /* prep */
+        { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
+        { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
+        { 0x70020112UL, 0x00000008UL }  /* prep */
       },
       { /* HuaTianSongTi */
-        { 0xfffbfffc, 0x00000008 }, /* cvt  */
-        { 0x0a5a0483, 0x00017c39 }, /* fpgm */
-        { 0x70020112, 0x00000008 }  /* prep */
+        { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
+        { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
+        { 0x70020112UL, 0x00000008UL }  /* prep */
       },
       { /* NEC fadpop7.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x40c92555, 0x000000e5 }, /* fpgm */
-        { 0xa39b58e3, 0x0000117c }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
+        { 0xA39B58E3UL, 0x0000117CUL }  /* prep */
       },
       { /* NEC fadrei5.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x33c41652, 0x000000e5 }, /* fpgm */
-        { 0x26d6c52a, 0x00000f6a }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
+        { 0x26D6C52AUL, 0x00000F6AUL }  /* prep */
       },
       { /* NEC fangot7.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x6db1651d, 0x0000019d }, /* fpgm */
-        { 0x6c6e4b03, 0x00002492 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
+        { 0x6C6E4B03UL, 0x00002492UL }  /* prep */
       },
       { /* NEC fangyo5.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x40c92555, 0x000000e5 }, /* fpgm */
-        { 0xde51fad0, 0x0000117c }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
+        { 0xDE51FAD0UL, 0x0000117CUL }  /* prep */
       },
       { /* NEC fankyo5.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x85e47664, 0x000000e5 }, /* fpgm */
-        { 0xa6c62831, 0x00001caa }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
+        { 0xA6C62831UL, 0x00001CAAUL }  /* prep */
       },
       { /* NEC fanrgo5.ttf */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x2d891cfd, 0x0000019d }, /* fpgm */
-        { 0xa0604633, 0x00001de8 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
+        { 0xA0604633UL, 0x00001DE8UL }  /* prep */
       },
       { /* NEC fangot5.ttc */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x40aa774c, 0x000001cb }, /* fpgm */
-        { 0x9b5caa96, 0x00001f9a }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
+        { 0x9B5CAA96UL, 0x00001F9AUL }  /* prep */
       },
       { /* NEC fanmin3.ttc */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x0d3de9cb, 0x00000141 }, /* fpgm */
-        { 0xd4127766, 0x00002280 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
+        { 0xD4127766UL, 0x00002280UL }  /* prep */
       },
       { /* NEC FA-Gothic, 1996 */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x4a692698, 0x000001f0 }, /* fpgm */
-        { 0x340d4346, 0x00001fca }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
+        { 0x340D4346UL, 0x00001FCAUL }  /* prep */
       },
       { /* NEC FA-Minchou, 1996 */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0xcd34c604, 0x00000166 }, /* fpgm */
-        { 0x6cf31046, 0x000022b0 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
+        { 0x6CF31046UL, 0x000022B0UL }  /* prep */
       },
       { /* NEC FA-RoundGothicB, 1996 */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0x5da75315, 0x0000019d }, /* fpgm */
-        { 0x40745a5f, 0x000022e0 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
+        { 0x40745A5FUL, 0x000022E0UL }  /* prep */
       },
       { /* NEC FA-RoundGothicM, 1996 */
-        { 0x00000000, 0x00000000 }, /* cvt  */
-        { 0xf055fc48, 0x000001c2 }, /* fpgm */
-        { 0x3900ded3, 0x00001e18 }  /* prep */
+        { 0x00000000UL, 0x00000000UL }, /* cvt  */
+        { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
+        { 0x3900DED3UL, 0x00001E18UL }  /* prep */
       }
     };
 
@@ -397,11 +398,11 @@
     for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
     {
       if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
         return TRUE;
     }
@@ -490,7 +491,10 @@
   /* <Input>                                                               */
   /*    stream     :: The source font stream.                              */
   /*                                                                       */
-  /*    face_index :: The index of the font face in the resource.          */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection, in bits 0-15.  The numbered instance     */
+  /*                  index~+~1 of a GX (sub)font, if applicable, in bits  */
+  /*                  16-30.                                               */
   /*                                                                       */
   /*    num_params :: Number of additional generic parameters.  Ignored.   */
   /*                                                                       */
@@ -599,7 +603,7 @@
         ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
       }
 
-#else
+#else /* !FT_CONFIG_OPTION_INCREMENTAL */
 
       if ( !error )
         error = tt_face_load_loca( face, stream );
@@ -623,32 +627,55 @@
         ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
       }
 
-#endif
+#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
 
     }
 
-#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING    ) && \
-    !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
     {
-      FT_Bool  unpatented_hinting;
-      int      i;
+      FT_Int  instance_index = face_index >> 16;
 
 
-      /* Determine whether unpatented hinting is to be used for this face. */
-      unpatented_hinting = FT_BOOL
-        ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL );
+      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
+           instance_index > 0                )
+      {
+        error = TT_Get_MM_Var( face, NULL );
+        if ( error )
+          goto Exit;
 
-      for ( i = 0; i < num_params && !face->unpatented_hinting; i++ )
-        if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )
-          unpatented_hinting = TRUE;
+        if ( face->blend->mmvar->namedstyle )
+        {
+          FT_Memory  memory = ttface->memory;
 
-      if ( !unpatented_hinting )
-        ttface->internal->ignore_unpatented_hinter = TRUE;
+          FT_Var_Named_Style*  named_style;
+          FT_String*           style_name;
+
+
+          /* in `face_index', the instance index starts with value 1 */
+          named_style = face->blend->mmvar->namedstyle + instance_index - 1;
+          error = sfnt->get_name( face,
+                                  (FT_UShort)named_style->strid,
+                                  &style_name );
+          if ( error )
+            goto Exit;
+
+          /* set style name; if already set, replace it */
+          if ( face->root.style_name )
+            FT_FREE( face->root.style_name );
+          face->root.style_name = style_name;
+
+          /* finally, select the named instance */
+          error = TT_Set_Var_Design( face,
+                                     face->blend->mmvar->num_axis,
+                                     named_style->coords );
+          if ( error )
+            goto Exit;
+        }
+      }
     }
 
-#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
-          !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
     /* initialize standard glyph loading routines */
     TT_Init_Glyph_Loading( face );
@@ -751,16 +778,11 @@
     FT_Error        error;
 
 
-    /* debugging instances have their own context */
-    if ( size->debug )
-      exec = size->context;
-    else
-      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+    exec = size->context;
 
-    if ( !exec )
-      return FT_THROW( Could_Not_Find_Context );
-
-    TT_Load_Context( exec, face, size );
+    error = TT_Load_Context( exec, face, size );
+    if ( error )
+      return error;
 
     exec->callTop = 0;
     exec->top     = 0;
@@ -793,7 +815,7 @@
     TT_Set_CodeRange( exec,
                       tt_coderange_font,
                       face->font_program,
-                      face->font_program_size );
+                      (FT_Long)face->font_program_size );
 
     /* disable CVT and glyph programs coderange */
     TT_Clear_CodeRange( exec, tt_coderange_cvt );
@@ -801,14 +823,10 @@
 
     if ( face->font_program_size > 0 )
     {
-      error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+      TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
 
-      if ( !error )
-      {
-        FT_TRACE4(( "Executing `fpgm' table.\n" ));
-
-        error = face->interpreter( exec );
-      }
+      FT_TRACE4(( "Executing `fpgm' table.\n" ));
+      error = face->interpreter( exec );
     }
     else
       error = FT_Err_Ok;
@@ -847,16 +865,11 @@
     FT_Error        error;
 
 
-    /* debugging instances have their own context */
-    if ( size->debug )
-      exec = size->context;
-    else
-      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+    exec = size->context;
 
-    if ( !exec )
-      return FT_THROW( Could_Not_Find_Context );
-
-    TT_Load_Context( exec, face, size );
+    error = TT_Load_Context( exec, face, size );
+    if ( error )
+      return error;
 
     exec->callTop = 0;
     exec->top     = 0;
@@ -868,20 +881,17 @@
     TT_Set_CodeRange( exec,
                       tt_coderange_cvt,
                       face->cvt_program,
-                      face->cvt_program_size );
+                      (FT_Long)face->cvt_program_size );
 
     TT_Clear_CodeRange( exec, tt_coderange_glyph );
 
     if ( face->cvt_program_size > 0 )
     {
-      error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+      TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
 
-      if ( !error && !size->debug )
-      {
-        FT_TRACE4(( "Executing `prep' table.\n" ));
+      FT_TRACE4(( "Executing `prep' table.\n" ));
 
-        error = face->interpreter( exec );
-      }
+      error = face->interpreter( exec );
     }
     else
       error = FT_Err_Ok;
@@ -924,12 +934,10 @@
     TT_Face    face   = (TT_Face)ftsize->face;
     FT_Memory  memory = face->root.memory;
 
-
-    if ( size->debug )
+    if ( size->context )
     {
-      /* the debug context must be deleted by the debugger itself */
+      TT_Done_Context( size->context );
       size->context = NULL;
-      size->debug   = FALSE;
     }
 
     FT_FREE( size->cvt );
@@ -968,15 +976,26 @@
     TT_Size    size = (TT_Size)ftsize;
     TT_Face    face = (TT_Face)ftsize->face;
     FT_Memory  memory = face->root.memory;
-    FT_Int     i;
 
     FT_UShort       n_twilight;
     TT_MaxProfile*  maxp = &face->max_profile;
 
 
+    /* clean up bytecode related data */
+    FT_FREE( size->function_defs );
+    FT_FREE( size->instruction_defs );
+    FT_FREE( size->cvt );
+    FT_FREE( size->storage );
+
+    if ( size->context )
+      TT_Done_Context( size->context );
+    tt_glyphzone_done( &size->twilight );
+
     size->bytecode_ready = -1;
     size->cvt_ready      = -1;
 
+    size->context = TT_New_Context( (TT_Driver)face->root.driver );
+
     size->max_function_defs    = maxp->maxFunctionDefs;
     size->max_instruction_defs = maxp->maxInstructionDefs;
 
@@ -997,9 +1016,11 @@
       metrics->rotated   = FALSE;
       metrics->stretched = FALSE;
 
-      /* set default compensation (all 0) */
-      for ( i = 0; i < 4; i++ )
-        metrics->compensations[i] = 0;
+      /* set default engine compensation */
+      metrics->compensations[0] = 0;   /* gray     */
+      metrics->compensations[1] = 0;   /* black    */
+      metrics->compensations[2] = 0;   /* white    */
+      metrics->compensations[3] = 0;   /* reserved */
     }
 
     /* allocate function defs, instruction defs, cvt, and storage area */
@@ -1035,7 +1056,15 @@
     }
 
     /* Fine, now run the font program! */
+
+    /* In case of an error while executing `fpgm', we intentionally don't */
+    /* clean up immediately – bugs in the `fpgm' are so fundamental that  */
+    /* all following hinting calls should fail.  Additionally, `fpgm' is  */
+    /* to be executed just once; calling it again is completely useless   */
+    /* and might even lead to extremely slow behaviour if it is malformed */
+    /* (containing an infinite loop, for example).                        */
     error = tt_size_run_fpgm( size, pedantic );
+    return error;
 
   Exit:
     if ( error )
@@ -1115,6 +1144,7 @@
     TT_Size   size  = (TT_Size)ttsize;
     FT_Error  error = FT_Err_Ok;
 
+
 #ifdef TT_USE_BYTECODE_INTERPRETER
     size->bytecode_ready = -1;
     size->cvt_ready      = -1;
@@ -1145,8 +1175,7 @@
 
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
-    if ( size->bytecode_ready >= 0 )
-      tt_size_done_bytecode( ttsize );
+    tt_size_done_bytecode( ttsize );
 #endif
 
     size->ttmetrics.valid = FALSE;
@@ -1258,14 +1287,12 @@
 
     TT_Driver  driver = (TT_Driver)ttdriver;
 
-
-    if ( !TT_New_Context( driver ) )
-      return FT_THROW( Could_Not_Find_Context );
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
-#else
     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    driver->interpreter_version = TT_INTERPRETER_VERSION_40;
 #endif
 
 #else /* !TT_USE_BYTECODE_INTERPRETER */
@@ -1292,20 +1319,7 @@
   FT_LOCAL_DEF( void )
   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
   {
-#ifdef TT_USE_BYTECODE_INTERPRETER
-    TT_Driver  driver = (TT_Driver)ttdriver;
-
-
-    /* destroy the execution context */
-    if ( driver->context )
-    {
-      TT_Done_Context( driver->context );
-      driver->context = NULL;
-    }
-#else
     FT_UNUSED( ttdriver );
-#endif
-
   }
 
 
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 47d50d9..98ad383 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2009, 2011-2014 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTOBJS_H__
-#define __TTOBJS_H__
+#ifndef TTOBJS_H_
+#define TTOBJS_H_
 
 
 #include <ft2build.h>
@@ -42,17 +42,6 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Type>                                                                */
-  /*    TT_Instance                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A handle to a TrueType size object.                                */
-  /*                                                                       */
-  typedef struct TT_SizeRec_*  TT_Size;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Type>                                                                */
   /*    TT_GlyphSlot                                                       */
   /*                                                                       */
   /* <Description>                                                         */
@@ -83,10 +72,6 @@
     FT_UnitVector  projVector;
     FT_UnitVector  freeVector;
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_Bool        both_x_axis;
-#endif
-
     FT_Long        loop;
     FT_F26Dot6     minimum_distance;
     FT_Int         round_state;
@@ -95,8 +80,8 @@
     FT_F26Dot6     control_value_cutin;
     FT_F26Dot6     single_width_cutin;
     FT_F26Dot6     single_width_value;
-    FT_Short       delta_base;
-    FT_Short       delta_shift;
+    FT_UShort      delta_base;
+    FT_UShort      delta_shift;
 
     FT_Byte        instruct_control;
     /* According to Greg Hitchcock from Microsoft, the `scan_control'     */
@@ -160,7 +145,7 @@
   typedef struct  TT_CodeRange_
   {
     FT_Byte*  base;
-    FT_ULong  size;
+    FT_Long   size;
 
   } TT_CodeRange;
 
@@ -301,6 +286,8 @@
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
+    FT_Long            point_size;    /* for the `MPS' bytecode instruction */
+
     FT_UInt            num_function_defs; /* number of function definitions */
     FT_UInt            max_function_defs;
     TT_DefArray        function_defs;     /* table of function definitions  */
@@ -324,13 +311,6 @@
 
     TT_GlyphZoneRec    twilight;     /* The instance's twilight zone    */
 
-    /* debugging variables */
-
-    /* When using the debugger, we must keep the */
-    /* execution context tied to the instance    */
-    /* object rather than asking it on demand.   */
-
-    FT_Bool            debug;
     TT_ExecContext     context;
 
     /* if negative, `fpgm' (resp. `prep'), wasn't executed yet; */
@@ -351,7 +331,6 @@
   {
     FT_DriverRec  root;
 
-    TT_ExecContext   context;  /* execution context        */
     TT_GlyphZoneRec  zone;     /* glyph loader points zone */
 
     FT_UInt  interpreter_version;
@@ -438,7 +417,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTOBJS_H__ */
+#endif /* TTOBJS_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttpic.c b/src/truetype/ttpic.c
index edefae7..54a5b8b 100644
--- a/src/truetype/ttpic.c
+++ b/src/truetype/ttpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for truetype module. */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2012, 2013 by                                    */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/src/truetype/ttpic.h b/src/truetype/ttpic.h
index cfb4ee6..f725865 100644
--- a/src/truetype/ttpic.h
+++ b/src/truetype/ttpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for truetype module. */
 /*                                                                         */
-/*  Copyright 2009, 2012, 2013 by                                          */
+/*  Copyright 2009-2016 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,11 +16,12 @@
 /***************************************************************************/
 
 
-#ifndef __TTPIC_H__
-#define __TTPIC_H__
+#ifndef TTPIC_H_
+#define TTPIC_H_
 
 
-FT_BEGIN_HEADER
+#include FT_INTERNAL_PIC_H
+
 
 #ifndef FT_CONFIG_OPTION_PIC
 
@@ -37,6 +38,8 @@
 #include FT_SERVICE_PROPERTIES_H
 
 
+FT_BEGIN_HEADER
+
   typedef struct  TTModulePIC_
   {
     FT_ServiceDescRec*          tt_services;
@@ -68,14 +71,13 @@
   FT_Error
   tt_driver_class_pic_init( FT_Library  library );
 
+FT_END_HEADER
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
  /* */
 
-
-FT_END_HEADER
-
-#endif /* __TTPIC_H__ */
+#endif /* TTPIC_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 9723a51..ca158ac 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2013 by                                      */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -118,40 +118,52 @@
       /* we only handle the case where `maxp' gives a larger value */
       if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
       {
-        FT_Long   new_loca_len =
-                    ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
+        FT_ULong  new_loca_len =
+                    ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
 
         TT_Table  entry = face->dir_tables;
         TT_Table  limit = entry + face->num_tables;
 
-        FT_Long   pos  = FT_Stream_Pos( stream );
-        FT_Long   dist = 0x7FFFFFFFL;
+        FT_Long  pos   = (FT_Long)FT_STREAM_POS();
+        FT_Long  dist  = 0x7FFFFFFFL;
+        FT_Bool  found = 0;
 
 
         /* compute the distance to next table in font file */
         for ( ; entry < limit; entry++ )
         {
-          FT_Long  diff = entry->Offset - pos;
+          FT_Long  diff = (FT_Long)entry->Offset - pos;
 
 
           if ( diff > 0 && diff < dist )
-            dist = diff;
+          {
+            dist  = diff;
+            found = 1;
+          }
         }
 
-        if ( entry == limit )
+        if ( !found )
         {
           /* `loca' is the last table */
-          dist = stream->size - pos;
+          dist = (FT_Long)stream->size - pos;
         }
 
-        if ( new_loca_len <= dist )
+        if ( new_loca_len <= (FT_ULong)dist )
         {
-          face->num_locations = face->root.num_glyphs + 1;
+          face->num_locations = (FT_ULong)face->root.num_glyphs + 1;
           table_len           = new_loca_len;
 
           FT_TRACE2(( "adjusting num_locations to %d\n",
                       face->num_locations ));
         }
+        else
+        {
+          face->root.num_glyphs = face->num_locations
+                                    ? (FT_Long)face->num_locations - 1 : 0;
+
+          FT_TRACE2(( "adjusting num_glyphs to %d\n",
+                      face->root.num_glyphs ));
+        }
       }
     }
 
@@ -214,7 +226,8 @@
     if ( pos1 > face->glyf_len )
     {
       FT_TRACE1(( "tt_face_get_location:"
-                  " too large offset=0x%08lx found for gid=0x%04lx,"
+                  " too large offset=0x%08lx found for gid=0x%04lx,\n"
+                  "                     "
                   " exceeding the end of glyf table (0x%08lx)\n",
                   pos1, gindex, face->glyf_len ));
       *asize = 0;
@@ -224,7 +237,8 @@
     if ( pos2 > face->glyf_len )
     {
       FT_TRACE1(( "tt_face_get_location:"
-                  " too large offset=0x%08lx found for gid=0x%04lx,"
+                  " too large offset=0x%08lx found for gid=0x%04lx,\n"
+                  "                     "
                   " truncate at the end of glyf table (0x%08lx)\n",
                   pos2, gindex + 1, face->glyf_len ));
       pos2 = face->glyf_len;
@@ -508,9 +522,9 @@
     record_size = FT_NEXT_ULONG( p );
 
     /* The maximum number of bytes in an hdmx device record is the */
-    /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
-    /* the reason why `record_size' is a long (which we read as    */
-    /* unsigned long for convenience).  In practice, two bytes     */
+    /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus      */
+    /* explaining why `record_size' is a long (which we read as    */
+    /* unsigned long for convenience).  In practice, two bytes are */
     /* sufficient to hold the size value.                          */
     /*                                                             */
     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
@@ -522,8 +536,10 @@
       record_size &= 0xFFFFU;
 
     /* The limit for `num_records' is a heuristic value. */
-
-    if ( version != 0 || num_records > 255 || record_size > 0x10001L )
+    if ( version != 0           ||
+         num_records > 255      ||
+         record_size > 0x10001L ||
+         record_size < 4        )
     {
       error = FT_THROW( Invalid_File_Format );
       goto Fail;
diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h
index f61ac07..aa2e38e 100644
--- a/src/truetype/ttpload.h
+++ b/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2005, 2006 by                               */
+/*  Copyright 1996-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTPLOAD_H__
-#define __TTPLOAD_H__
+#ifndef TTPLOAD_H_
+#define TTPLOAD_H_
 
 
 #include <ft2build.h>
@@ -69,7 +69,7 @@
 
 FT_END_HEADER
 
-#endif /* __TTPLOAD_H__ */
+#endif /* TTPLOAD_H_ */
 
 
 /* END */
diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
index 9871994..0395096 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Subpixel Hinting.                                           */
 /*                                                                         */
-/*  Copyright 2010-2013 by                                                 */
+/*  Copyright 2010-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,7 @@
 #include "ttsubpix.h"
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -63,8 +63,8 @@
   /* rules below.  A blank entry "" is required at the end of these!       */
 #define FAMILY_CLASS_RULES_SIZE  7
 
-  static const SPH_Font_Class FAMILY_CLASS_Rules
-                              [FAMILY_CLASS_RULES_SIZE] =
+  static const SPH_Font_Class  FAMILY_CLASS_Rules
+                               [FAMILY_CLASS_RULES_SIZE] =
   {
     { "MS Legacy Fonts",
       { "Aharoni",
@@ -223,8 +223,8 @@
   /* rules below.  A blank entry "" is required at the end of these!       */
 #define STYLE_CLASS_RULES_SIZE  5
 
-  const SPH_Font_Class STYLE_CLASS_Rules
-                       [STYLE_CLASS_RULES_SIZE] =
+  static const SPH_Font_Class  STYLE_CLASS_Rules
+                               [STYLE_CLASS_RULES_SIZE] =
   {
     { "Regular Class",
       { "Regular",
@@ -279,18 +279,18 @@
   /* Force special legacy fixes for fonts.                                 */
 #define COMPATIBILITY_MODE_RULES_SIZE  1
 
-  const SPH_TweakRule  COMPATIBILITY_MODE_Rules
-                       [COMPATIBILITY_MODE_RULES_SIZE] =
+  static const SPH_TweakRule  COMPATIBILITY_MODE_Rules
+                              [COMPATIBILITY_MODE_RULES_SIZE] =
   {
-    { "-", 0, "", 0 },
+    { "Verdana Clones", 0, "", 0 },
   };
 
 
   /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting.         */
 #define PIXEL_HINTING_RULES_SIZE  2
 
-  const SPH_TweakRule  PIXEL_HINTING_Rules
-                       [PIXEL_HINTING_RULES_SIZE] =
+  static const SPH_TweakRule  PIXEL_HINTING_Rules
+                              [PIXEL_HINTING_RULES_SIZE] =
   {
     /* these characters are almost always safe */
     { "Courier New", 12, "Italic", 'z' },
@@ -301,8 +301,8 @@
   /* Subpixel hinting ignores SHPIX rules on X.  Force SHPIX for these.    */
 #define DO_SHPIX_RULES_SIZE  1
 
-  const SPH_TweakRule  DO_SHPIX_Rules
-                       [DO_SHPIX_RULES_SIZE] =
+  static const SPH_TweakRule  DO_SHPIX_Rules
+                              [DO_SHPIX_RULES_SIZE] =
   {
     { "-", 0, "", 0 },
   };
@@ -312,8 +312,8 @@
   /* boundary and don't move that point to a Y pixel boundary.             */
 #define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE  4
 
-  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules
-                       [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
+  static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules
+                              [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
   {
     /* fix vwxyz thinness*/
     { "Consolas", 0, "", 0 },
@@ -328,8 +328,8 @@
 
 #define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
 
-  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
-                       [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
+                              [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
   {
     /* Fixes < and > */
     { "Courier New", 0, "Regular", 0 },
@@ -340,8 +340,8 @@
   /* boundary and don't move that point to a Y pixel boundary.             */
 #define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE  2
 
-  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
-                       [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
+  static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
+                              [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
   {
     /* Maintain thickness of diagonal in 'N' */
     { "Times New Roman", 0, "Regular/Bold Class", 'N' },
@@ -352,8 +352,8 @@
   /* Skip Y moves that move a point off a Y pixel boundary.                */
 #define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE  1
 
-  const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules
-                       [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
+  static const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules
+                              [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
   {
     { "-", 0, "", 0 },
   };
@@ -361,8 +361,8 @@
 
 #define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
 
-  const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
-                       [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  static const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
+                              [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
   {
     { "-", 0, "", 0 },
   };
@@ -371,8 +371,8 @@
   /* Round moves that don't move a point to a Y pixel boundary.            */
 #define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE  2
 
-  const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules
-                       [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
+  static const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules
+                              [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
   {
     /* Droid font instructions don't snap Y to pixels */
     { "Droid Sans", 0, "Regular/Italic Class", 0 },
@@ -382,8 +382,8 @@
 
 #define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
 
-  const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
-                       [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  static const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
+                              [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
   {
     { "-", 0, "", 0 },
   };
@@ -392,8 +392,8 @@
   /* Allow a Direct_Move along X freedom vector if matched.                */
 #define ALLOW_X_DMOVE_RULES_SIZE  1
 
-  const SPH_TweakRule  ALLOW_X_DMOVE_Rules
-                       [ALLOW_X_DMOVE_RULES_SIZE] =
+  static const SPH_TweakRule  ALLOW_X_DMOVE_Rules
+                              [ALLOW_X_DMOVE_RULES_SIZE] =
   {
     /* Fixes vanishing diagonal in 4 */
     { "Verdana", 0, "Regular", '4' },
@@ -403,8 +403,8 @@
   /* Return MS rasterizer version 35 if matched.                           */
 #define RASTERIZER_35_RULES_SIZE  8
 
-  const SPH_TweakRule  RASTERIZER_35_Rules
-                       [RASTERIZER_35_RULES_SIZE] =
+  static const SPH_TweakRule  RASTERIZER_35_Rules
+                              [RASTERIZER_35_RULES_SIZE] =
   {
     /* This seems to be the only way to make these look good */
     { "Times New Roman", 0, "Regular", 'i' },
@@ -421,8 +421,8 @@
   /* Don't round to the subpixel grid.  Round to pixel grid.               */
 #define NORMAL_ROUND_RULES_SIZE  1
 
-  const SPH_TweakRule  NORMAL_ROUND_Rules
-                       [NORMAL_ROUND_RULES_SIZE] =
+  static const SPH_TweakRule  NORMAL_ROUND_Rules
+                              [NORMAL_ROUND_RULES_SIZE] =
   {
     /* Fix serif thickness for certain ppems */
     /* Can probably be generalized somehow   */
@@ -433,8 +433,8 @@
   /* Skip IUP instructions if matched.                                     */
 #define SKIP_IUP_RULES_SIZE  1
 
-  const SPH_TweakRule  SKIP_IUP_Rules
-                       [SKIP_IUP_RULES_SIZE] =
+  static const SPH_TweakRule  SKIP_IUP_Rules
+                              [SKIP_IUP_RULES_SIZE] =
   {
     { "Arial", 13, "Regular", 'a' },
   };
@@ -443,8 +443,8 @@
   /* Skip MIAP Twilight hack if matched.                                   */
 #define MIAP_HACK_RULES_SIZE  1
 
-  const SPH_TweakRule  MIAP_HACK_Rules
-                       [MIAP_HACK_RULES_SIZE] =
+  static const SPH_TweakRule  MIAP_HACK_Rules
+                              [MIAP_HACK_RULES_SIZE] =
   {
     { "Geneva", 12, "", 0 },
   };
@@ -453,8 +453,8 @@
   /* Skip DELTAP instructions if matched.                                  */
 #define ALWAYS_SKIP_DELTAP_RULES_SIZE  23
 
-  const SPH_TweakRule  ALWAYS_SKIP_DELTAP_Rules
-                       [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
+  static const SPH_TweakRule  ALWAYS_SKIP_DELTAP_Rules
+                              [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
   {
     { "Georgia", 0, "Regular", 'k' },
     /* fix various problems with e in different versions */
@@ -489,8 +489,8 @@
   /* Always do DELTAP instructions if matched.                             */
 #define ALWAYS_DO_DELTAP_RULES_SIZE  1
 
-  const SPH_TweakRule  ALWAYS_DO_DELTAP_Rules
-                       [ALWAYS_DO_DELTAP_RULES_SIZE] =
+  static const SPH_TweakRule  ALWAYS_DO_DELTAP_Rules
+                              [ALWAYS_DO_DELTAP_RULES_SIZE] =
   {
     { "-", 0, "", 0 },
   };
@@ -744,7 +744,7 @@
 #endif /* FORCE_NATURAL_WIDTHS */
 
 
-  FT_LOCAL_DEF( FT_Bool )
+  static FT_Bool
   is_member_of_family_class( const FT_String*  detected_font_name,
                              const FT_String*  rule_font_name )
   {
@@ -779,7 +779,7 @@
   }
 
 
-  FT_LOCAL_DEF( FT_Bool )
+  static FT_Bool
   is_member_of_style_class( const FT_String*  detected_font_style,
                             const FT_String*  rule_font_style )
   {
@@ -903,9 +903,9 @@
   sph_set_tweaks( TT_Loader  loader,
                   FT_UInt    glyph_index )
   {
-    TT_Face     face   = (TT_Face)loader->face;
+    TT_Face     face   = loader->face;
     FT_String*  family = face->root.family_name;
-    int         ppem   = loader->size->metrics.x_ppem;
+    FT_UInt     ppem   = loader->size->metrics.x_ppem;
     FT_String*  style  = face->root.style_name;
 
 
@@ -1000,12 +1000,12 @@
     }
   }
 
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   /* ANSI C doesn't like empty source files */
   typedef int  _tt_subpix_dummy;
 
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
 /* END */
diff --git a/src/truetype/ttsubpix.h b/src/truetype/ttsubpix.h
index 8a54fc7..86844da 100644
--- a/src/truetype/ttsubpix.h
+++ b/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Subpixel Hinting.                                           */
 /*                                                                         */
-/*  Copyright 2010-2013 by                                                 */
+/*  Copyright 2010-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __TTSUBPIX_H__
-#define __TTSUBPIX_H__
+#ifndef TTSUBPIX_H_
+#define TTSUBPIX_H_
 
 #include <ft2build.h>
 #include "ttobjs.h"
@@ -27,7 +27,7 @@
 FT_BEGIN_HEADER
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -50,26 +50,26 @@
   /* Tweak flags that are set for each glyph by the below rules.           */
   /*                                                                       */
   /*                                                                       */
-#define SPH_TWEAK_ALLOW_X_DMOVE                   0x0000001
-#define SPH_TWEAK_ALWAYS_DO_DELTAP                0x0000002
-#define SPH_TWEAK_ALWAYS_SKIP_DELTAP              0x0000004
-#define SPH_TWEAK_COURIER_NEW_2_HACK              0x0000008
-#define SPH_TWEAK_DEEMBOLDEN                      0x0000010
-#define SPH_TWEAK_DO_SHPIX                        0x0000020
-#define SPH_TWEAK_EMBOLDEN                        0x0000040
-#define SPH_TWEAK_MIAP_HACK                       0x0000080
-#define SPH_TWEAK_NORMAL_ROUND                    0x0000100
-#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP            0x0000200
-#define SPH_TWEAK_NO_CALL_AFTER_IUP               0x0000400
-#define SPH_TWEAK_NO_DELTAP_AFTER_IUP             0x0000800
-#define SPH_TWEAK_PIXEL_HINTING                   0x0001000
-#define SPH_TWEAK_RASTERIZER_35                   0x0002000
-#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES          0x0004000
-#define SPH_TWEAK_SKIP_IUP                        0x0008000
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES           0x0010000
-#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES           0x0020000
-#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK            0x0040000
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP    0x0080000
+#define SPH_TWEAK_ALLOW_X_DMOVE                   0x0000001UL
+#define SPH_TWEAK_ALWAYS_DO_DELTAP                0x0000002UL
+#define SPH_TWEAK_ALWAYS_SKIP_DELTAP              0x0000004UL
+#define SPH_TWEAK_COURIER_NEW_2_HACK              0x0000008UL
+#define SPH_TWEAK_DEEMBOLDEN                      0x0000010UL
+#define SPH_TWEAK_DO_SHPIX                        0x0000020UL
+#define SPH_TWEAK_EMBOLDEN                        0x0000040UL
+#define SPH_TWEAK_MIAP_HACK                       0x0000080UL
+#define SPH_TWEAK_NORMAL_ROUND                    0x0000100UL
+#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP            0x0000200UL
+#define SPH_TWEAK_NO_CALL_AFTER_IUP               0x0000400UL
+#define SPH_TWEAK_NO_DELTAP_AFTER_IUP             0x0000800UL
+#define SPH_TWEAK_PIXEL_HINTING                   0x0001000UL
+#define SPH_TWEAK_RASTERIZER_35                   0x0002000UL
+#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES          0x0004000UL
+#define SPH_TWEAK_SKIP_IUP                        0x0008000UL
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES           0x0010000UL
+#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES           0x0020000UL
+#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK            0x0040000UL
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP    0x0080000UL
 
 
   FT_LOCAL( FT_Bool )
@@ -100,11 +100,12 @@
 #define SPH_OPTION_SET_COMPATIBLE_WIDTHS   FALSE
 #define SPH_OPTION_SET_RASTERIZER_VERSION  38
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
 FT_END_HEADER
 
-#endif /* __TTSUBPIX_H__ */
+#endif /* TTSUBPIX_H_ */
+
 
 /* END */