Update FreeType from 2.6.2 to c38be52bf8de (2.7 + a few post-2.7 CLs)

http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=c38be52b

Keep all the configuration options as before.

Likewise, exclude unused files (Jamfiles, various mk files, builds/,
docs/, ChangeLog*, directories under src/ for disabled modules, etc).

Update README.android to record the configurations.

Besides, disable a new option (TT_CONFIG_OPTION_SUBPIXEL_HINTING) for
branches. Note that a bulk of changes in this CL come from the code to
implement this option.

BUG: 31470908
Change-Id: I1ca90aec171d9580415b8531e2b767e9dd31164c
diff --git a/Android.mk b/Android.mk
index 138ac69..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.6.2
+USE_FREETYPE := 2.7
 endif
 
-ifeq ($(USE_FREETYPE),2.6.2)
+ifeq ($(USE_FREETYPE),2.7)
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
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
index ed61907..3f599a0 100644
--- a/README.android
+++ b/README.android
@@ -1,4 +1,21 @@
 Freetype
 
-Not all modules in include/config/ftmodule.h are enabled.
-Some options in include/config/ftoption.h are enabled/disabled.
+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
index c935690..6d57025 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://download.savannah.gnu.org/releases/freetype/freetype-2.5.3.tar.bz2
-Version: 2.5.3
+URL: http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=c38be52b
+Version: c38be52bf8de3b1699d74932b849bf150265819e (2.7 + update)
 BugComponent: 75970
diff --git a/include/config/ftconfig.h b/include/freetype/config/ftconfig.h
similarity index 97%
rename from include/config/ftconfig.h
rename to include/freetype/config/ftconfig.h
index 086db76..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-2015 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
@@ -275,7 +275,13 @@
   /*                                                                       */
 #elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
 
-#if defined( _MSC_VER ) && _MSC_VER >= 900  /* Visual C++ (and Intel C++) */
+#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 */
 #define FT_LONG64
@@ -309,7 +315,7 @@
 #define FT_INT64   long long int
 #define FT_UINT64  unsigned long long int
 
-#endif /* _MSC_VER */
+#endif /* __STDC_VERSION__ >= 199901L */
 
 #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
 
@@ -335,9 +341,9 @@
 #if ( __GNUC__ >= 2                         || \
       defined( __IBM__TYPEOF__ )            || \
       ( __SUNPRO_C >= 0x5110 && !__STDC__ ) )
-#define TYPEOF( type )  (__typeof__ (type))
+#define FT_TYPEOF( type )  (__typeof__ (type))
 #else
-#define TYPEOF( type )  /* empty */
+#define FT_TYPEOF( type )  /* empty */
 #endif
 
 
@@ -461,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 88%
rename from include/config/ftheader.h
rename to include/freetype/config/ftheader.h
index 4906bc1..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-2015 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,7 +704,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which performs artificial obliquing and emboldening.
    */
-#define FT_SYNTHESIS_H  <ftsynth.h>
+#define FT_SYNTHESIS_H  <freetype/ftsynth.h>
 
 
   /*************************************************************************
@@ -716,7 +716,7 @@
    *   A macro used in #include statements to name the file containing the
    *   FreeType~2 API which provides functions specific to font formats.
    */
-#define FT_FONT_FORMATS_H  <ftfntfmt.h>
+#define FT_FONT_FORMATS_H  <freetype/ftfntfmt.h>
 
   /* deprecated */
 #define FT_XFREE86_H  FT_FONT_FORMATS_H
@@ -732,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>
 
 
   /*************************************************************************
@@ -744,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>
 
 
   /*************************************************************************
@@ -753,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>
 
 
   /*************************************************************************
@@ -766,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>
 
 
   /*************************************************************************
@@ -780,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>
 
 
   /*************************************************************************
@@ -792,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>
 
 
   /*
@@ -823,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 100%
rename from include/config/ftmodule.h
rename to include/freetype/config/ftmodule.h
diff --git a/include/config/ftoption.h b/include/freetype/config/ftoption.h
similarity index 87%
rename from include/config/ftoption.h
rename to include/freetype/config/ftoption.h
index 6e8a528..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-2015 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,7 +59,7 @@
   /*    Note also that you can similarly pre-define the macro              */
   /*    FT_CONFIG_MODULES_H used to locate the file listing of the modules */
   /*    that are statically linked to the library at compile time.  By     */
-  /*    default, this file is <config/ftmodule.h>.                         */
+  /*    default, this file is <freetype/config/ftmodule.h>.                */
   /*                                                                       */
   /* 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.    */
   /*                                                                       */
@@ -492,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 */
 
@@ -586,73 +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_SUBPIXEL_HINTING  1         */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  2         */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  ( 1 | 2 ) */
 
 
   /*************************************************************************/
@@ -693,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       ****/
@@ -825,7 +867,7 @@
   /* `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
 
   /* */
 
@@ -838,14 +880,19 @@
 
 
   /*
-   * 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
 
 
@@ -880,7 +927,7 @@
 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 8ef43c0..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-2015 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,7 +142,8 @@
   /**********************************************************************/
 
 
-#define ft_atol  atol
+#define ft_strtol  strtol
+#define ft_getenv  getenv
 
 
   /**********************************************************************/
@@ -167,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 91%
rename from include/freetype.h
rename to include/freetype/freetype.h
index bca93e5..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-2015 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
@@ -141,7 +141,6 @@
   /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
   /*    FT_FACE_FLAG_EXTERNAL_STREAM                                       */
   /*    FT_FACE_FLAG_HINTER                                                */
-  /*    FT_FACE_FLAG_TRICKY                                                */
   /*                                                                       */
   /*    FT_HAS_HORIZONTAL                                                  */
   /*    FT_HAS_VERTICAL                                                    */
@@ -652,11 +651,11 @@
   /*                                                                       */
   /*    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 ::                                                */
@@ -876,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         */
@@ -933,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.       */
@@ -1085,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   */
@@ -1204,7 +1226,7 @@
    *
    */
 #define FT_HAS_HORIZONTAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+          ( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL )
 
 
   /*************************************************************************
@@ -1218,7 +1240,7 @@
    *
    */
 #define FT_HAS_VERTICAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+          ( (face)->face_flags & FT_FACE_FLAG_VERTICAL )
 
 
   /*************************************************************************
@@ -1232,7 +1254,7 @@
    *
    */
 #define FT_HAS_KERNING( face ) \
-          ( face->face_flags & FT_FACE_FLAG_KERNING )
+          ( (face)->face_flags & FT_FACE_FLAG_KERNING )
 
 
   /*************************************************************************
@@ -1247,7 +1269,7 @@
    *
    */
 #define FT_IS_SCALABLE( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+          ( (face)->face_flags & FT_FACE_FLAG_SCALABLE )
 
 
   /*************************************************************************
@@ -1266,7 +1288,7 @@
    *
    */
 #define FT_IS_SFNT( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SFNT )
+          ( (face)->face_flags & FT_FACE_FLAG_SFNT )
 
 
   /*************************************************************************
@@ -1281,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 )
 
 
   /*************************************************************************
@@ -1296,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 )
 
 
   /*************************************************************************
@@ -1322,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 )
 
 
   /*************************************************************************
@@ -1337,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 )
 
 
   /*************************************************************************
@@ -1355,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 )
 
 
   /*************************************************************************
@@ -1369,7 +1405,7 @@
    *
    */
 #define FT_IS_TRICKY( face ) \
-          ( face->face_flags & FT_FACE_FLAG_TRICKY )
+          ( (face)->face_flags & FT_FACE_FLAG_TRICKY )
 
 
   /*************************************************************************
@@ -1383,7 +1419,7 @@
    *
    */
 #define FT_HAS_COLOR( face ) \
-          ( face->face_flags & FT_FACE_FLAG_COLOR )
+          ( (face)->face_flags & FT_FACE_FLAG_COLOR )
 
 
   /*************************************************************************/
@@ -1392,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>                                                              */
@@ -1824,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>                                                              */
@@ -1923,7 +1959,7 @@
   /*                                                                       */
   /*    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.                                                     */
   /*                                                                       */
@@ -1971,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.                             */
@@ -2010,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.                             */
@@ -2048,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.                             */
@@ -2064,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'.               */
   /*                                                                       */
@@ -2084,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,
@@ -2227,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 */
@@ -2287,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;
@@ -2474,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,
@@ -2521,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:
@@ -2638,6 +2780,16 @@
    *     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.
    *
@@ -2683,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 )
 
   /* */
 
@@ -2705,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
@@ -2715,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
@@ -2740,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
@@ -2826,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 ::                                           */
@@ -2912,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 );
@@ -2927,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,
@@ -2972,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.                             */
@@ -3070,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,
@@ -3259,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.                  */
@@ -3454,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.                                                  */
@@ -3839,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 );
@@ -3858,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 );
@@ -3877,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 );
@@ -3957,7 +4209,7 @@
    *
    */
 #define FREETYPE_MAJOR  2
-#define FREETYPE_MINOR  6
+#define FREETYPE_MINOR  7
 #define FREETYPE_PATCH  0
 
 
@@ -4003,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.            */
@@ -4034,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.                                            */
@@ -4044,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.            */
@@ -4063,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 98%
rename from include/ftadvanc.h
rename to include/freetype/ftadvanc.h
index b4d2aed..023dd84 100644
--- a/include/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (specification only).            */
 /*                                                                         */
-/*  Copyright 2008-2015 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>
@@ -181,7 +181,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTADVANC_H__ */
+#endif /* FTADVANC_H_ */
 
 
 /* END */
diff --git a/include/ftautoh.h b/include/freetype/ftautoh.h
similarity index 84%
rename from include/ftautoh.h
rename to include/freetype/ftautoh.h
index cf7b76f..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-2015 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
    *     }
    *
@@ -247,8 +247,8 @@
    */
   typedef struct  FT_Prop_GlyphToScriptMap_
   {
-    FT_Face   face;
-    FT_Byte*  map;
+    FT_Face     face;
+    FT_UShort*  map;
 
   } FT_Prop_GlyphToScriptMap;
 
@@ -428,6 +428,9 @@
    * @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.
@@ -439,12 +442,70 @@
    */
 
 
+  /**************************************************************************
+   *
+   * @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 9d9d040..2a4d214 100644
--- a/include/ftbbox.h
+++ b/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType exact bbox computation (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -90,7 +90,7 @@
 
 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 0bdabf4..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-2015 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
@@ -204,7 +204,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTBDF_H__ */
+#endif /* FTBDF_H_ */
 
 
 /* END */
diff --git a/include/ftbitmap.h b/include/freetype/ftbitmap.h
similarity index 98%
rename from include/ftbitmap.h
rename to include/freetype/ftbitmap.h
index 46cc47b..0eac7b9 100644
--- a/include/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (specification).              */
 /*                                                                         */
-/*  Copyright 2004-2015 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>
@@ -234,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 c25f946..b7f2eee 100644
--- a/include/ftbzip2.h
+++ b/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Bzip2-compressed stream support.                                     */
 /*                                                                         */
-/*  Copyright 2010-2015 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
@@ -96,7 +96,7 @@
 
 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 68525bb..883c88d 100644
--- a/include/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Cache subsystem (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -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).                                    */
   /*                                                                       */
@@ -1051,7 +1051,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTCACHE_H__ */
+#endif /* FTCACHE_H_ */
 
 
 /* END */
diff --git a/include/ftcffdrv.h b/include/freetype/ftcffdrv.h
similarity index 89%
rename from include/ftcffdrv.h
rename to include/freetype/ftcffdrv.h
index 6c8e416..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-2015 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
@@ -110,9 +110,9 @@
    *   to minimize distortion.
    *
    * @order:
-   *   hinting-engine
-   *   no-stem-darkening
-   *   darkening-parameters
+   *   hinting-engine[cff]
+   *   no-stem-darkening[cff]
+   *   darkening-parameters[cff]
    *
    */
 
@@ -120,7 +120,7 @@
   /**************************************************************************
    *
    * @property:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *
    * @description:
    *   Thanks to Adobe, which contributed a new hinting (and parsing)
@@ -148,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').
    */
 
 
@@ -157,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 ::
@@ -175,7 +177,7 @@
   /**************************************************************************
    *
    * @property:
-   *   no-stem-darkening
+   *   no-stem-darkening[cff]
    *
    * @description:
    *   By default, the Adobe CFF engine darkens stems at smaller sizes,
@@ -199,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
@@ -248,6 +253,14 @@
    * @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
+   *   }
    */
 
   /* */
@@ -256,7 +269,7 @@
 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 95%
rename from include/ftcid.h
rename to include/freetype/ftcid.h
index 05741c8..e1bc9fe 100644
--- a/include/ftcid.h
+++ b/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for accessing CID font information (specification).     */
 /*                                                                         */
-/*  Copyright 2007-2015 by                                                 */
+/*  Copyright 2007-2016 by                                                 */
 /*  Dereg Clegg and Michael Toftdal.                                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __FTCID_H__
-#define __FTCID_H__
+#ifndef FTCID_H_
+#define FTCID_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -97,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 ::
@@ -162,7 +162,7 @@
 
 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 1bf0751..3f53dd5 100644
--- a/include/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType error codes (specification).                                */
 /*                                                                         */
-/*  Copyright 2002-2015 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/ftfntfmt.h b/include/freetype/ftfntfmt.h
similarity index 96%
rename from include/ftfntfmt.h
rename to include/freetype/ftfntfmt.h
index 1f8ff28..bd42324 100644
--- a/include/ftfntfmt.h
+++ b/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Support functions for font formats.                                  */
 /*                                                                         */
-/*  Copyright 2002-2015 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 __FTFNTFMT_H__
-#define __FTFNTFMT_H__
+#ifndef FTFNTFMT_H_
+#define FTFNTFMT_H_
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -89,4 +89,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTFNTFMT_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 9a9b632..3f5b3bc 100644
--- a/include/ftgasp.h
+++ b/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Access of TrueType's `gasp' table (specification).                   */
 /*                                                                         */
-/*  Copyright 2007-2015 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
@@ -123,7 +123,7 @@
   /* */
 
 
-#endif /* _FT_GASP_H_ */
+#endif /* FTGASP_H_ */
 
 
 /* END */
diff --git a/include/ftglyph.h b/include/freetype/ftglyph.h
similarity index 99%
rename from include/ftglyph.h
rename to include/freetype/ftglyph.h
index 803ad39..d9840a8 100644
--- a/include/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -594,7 +594,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTGLYPH_H__ */
+#endif /* FTGLYPH_H_ */
 
 
 /* END */
diff --git a/include/ftgxval.h b/include/freetype/ftgxval.h
similarity index 98%
rename from include/ftgxval.h
rename to include/freetype/ftgxval.h
index 0e9ac1d..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-2015 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
@@ -351,7 +351,7 @@
 
 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 b3a532d..3932ce6 100644
--- a/include/ftgzip.h
+++ b/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Gzip-compressed stream support.                                      */
 /*                                                                         */
-/*  Copyright 2002-2015 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.
@@ -142,7 +142,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTGZIP_H__ */
+#endif /* FTGZIP_H_ */
 
 
 /* END */
diff --git a/include/ftimage.h b/include/freetype/ftimage.h
similarity index 98%
rename from include/ftimage.h
rename to include/freetype/ftimage.h
index 82f284c..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-2015 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
 
@@ -747,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       */
@@ -860,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,
@@ -1203,7 +1193,7 @@
 
 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 840af25..46b58b7 100644
--- a/include/ftincrem.h
+++ b/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType incremental loading (specification).                        */
 /*                                                                         */
-/*  Copyright 2002-2015 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
@@ -348,7 +348,7 @@
 
 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 12b48c7..82f437a 100644
--- a/include/ftlist.h
+++ b/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Generic list support for FreeType (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -270,7 +270,7 @@
 
 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 d3ec28e..582e2c1 100644
--- a/include/ftlzw.h
+++ b/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    LZW-compressed stream support.                                       */
 /*                                                                         */
-/*  Copyright 2004-2015 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
@@ -93,7 +93,7 @@
 
 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 14c55cf..adb15ca 100644
--- a/include/ftmac.h
+++ b/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Additional Mac-specific API.                                         */
 /*                                                                         */
-/*  Copyright 1996-2015 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 94%
rename from include/ftmm.h
rename to include/freetype/ftmm.h
index 6ef4798..b5d6858 100644
--- a/include/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Multiple Master font interface (specification).             */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -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'.               */
+  /*                                                                       */
+  /*                       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.                         */
   /*                                                                       */
   /*    namedstyle      :: A named style table.                            */
   /*                       Only meaningful with GX.                        */
+  /*                       Memory management of this pointer is done       */
+  /*                       internally by FreeType.                         */
   /*                                                                       */
   typedef struct  FT_MM_Var_
   {
@@ -255,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.                             */
@@ -373,7 +382,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTMM_H__ */
+#endif /* FTMM_H_ */
 
 
 /* END */
diff --git a/include/ftmodapi.h b/include/freetype/ftmodapi.h
similarity index 96%
rename from include/ftmodapi.h
rename to include/freetype/ftmodapi.h
index 2ef3f46..b4d2758 100644
--- a/include/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType modules public interface (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2015 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                                                         */
@@ -111,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 */
@@ -125,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;
@@ -610,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
@@ -663,7 +661,7 @@
 
 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 9d7f981..2a7671c 100644
--- a/include/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType module error offsets (specification).                       */
 /*                                                                         */
-/*  Copyright 2001-2015 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 94%
rename from include/ftotval.h
rename to include/freetype/ftotval.h
index e744b71..3e6e18d 100644
--- a/include/ftotval.h
+++ b/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating OpenType tables (specification).         */
 /*                                                                         */
-/*  Copyright 2004-2015 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
@@ -106,12 +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 )
 
  /**********************************************************************
   *
@@ -198,7 +198,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTOTVAL_H__ */
+#endif /* FTOTVAL_H_ */
 
 
 /* END */
diff --git a/include/ftoutln.h b/include/freetype/ftoutln.h
similarity index 97%
rename from include/ftoutln.h
rename to include/freetype/ftoutln.h
index 106cfde..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-2015 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>
@@ -115,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,
@@ -213,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 );
 
@@ -354,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    */
@@ -563,7 +571,7 @@
 
 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 a1c02a2..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-2015 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
@@ -166,7 +166,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTPFR_H__ */
+#endif /* FTPFR_H_ */
 
 
 /* END */
diff --git a/include/ftrender.h b/include/freetype/ftrender.h
similarity index 98%
rename from include/ftrender.h
rename to include/freetype/ftrender.h
index ec8da70..9f7ed9e 100644
--- a/include/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType renderer modules public interface (specification).          */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -226,7 +226,7 @@
 
 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 bef8424..55e0d5c 100644
--- a/include/ftsizes.h
+++ b/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType size objects management (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2015 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 0f7fbe1..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-2015 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 99%
rename from include/ftstroke.h
rename to include/freetype/ftstroke.h
index 7ebb1e7..b3b9922 100644
--- a/include/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (specification).                               */
 /*                                                                         */
-/*  Copyright 2002-2015 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
@@ -774,7 +774,7 @@
 
 FT_END_HEADER
 
-#endif /* __FT_STROKE_H__ */
+#endif /* FTSTROKE_H_ */
 
 
 /* END */
diff --git a/include/ftsynth.h b/include/freetype/ftsynth.h
similarity index 96%
rename from include/ftsynth.h
rename to include/freetype/ftsynth.h
index fbcbad8..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-2015 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>
@@ -78,7 +78,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTSYNTH_H__ */
+#endif /* FTSYNTH_H_ */
 
 
 /* END */
diff --git a/include/ftsystem.h b/include/freetype/ftsystem.h
similarity index 98%
rename from include/ftsystem.h
rename to include/freetype/ftsystem.h
index 2bc9999..a75f958 100644
--- a/include/ftsystem.h
+++ b/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType low-level system interface definition (specification).      */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -290,7 +290,7 @@
    *     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. 
+   *     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.)
    *
@@ -349,7 +349,7 @@
 
 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 3d821ba..f789b52 100644
--- a/include/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (specification).                    */
 /*                                                                         */
-/*  Copyright 2001-2015 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.
@@ -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 99%
rename from include/fttypes.h
rename to include/freetype/fttypes.h
index 706a1be..2673e79 100644
--- a/include/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType simple types definitions (specification only).              */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -596,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 98%
rename from include/ftwinfnt.h
rename to include/freetype/ftwinfnt.h
index caedaa1..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-2015 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
@@ -264,7 +264,7 @@
 
 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 8d5a977..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-2015 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/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
similarity index 94%
rename from include/internal/ftcalc.h
rename to include/freetype/internal/ftcalc.h
index 75752c3..8a884f6 100644
--- a/include/internal/ftcalc.h
+++ b/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Arithmetic computations (specification).                             */
 /*                                                                         */
-/*  Copyright 1996-2015 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 __FTCALC_H__
-#define __FTCALC_H__
+#ifndef FTCALC_H_
+#define FTCALC_H_
 
 
 #include <ft2build.h>
@@ -47,7 +47,7 @@
   FT_MulFix_arm( FT_Int32  a,
                  FT_Int32  b )
   {
-    register FT_Int32  t, t2;
+    FT_Int32  t, t2;
 
 
     __asm
@@ -80,7 +80,7 @@
   FT_MulFix_arm( FT_Int32  a,
                  FT_Int32  b )
   {
-    register FT_Int32  t, t2;
+    FT_Int32  t, t2;
 
 
     __asm__ __volatile__ (
@@ -116,7 +116,7 @@
   FT_MulFix_i386( FT_Int32  a,
                   FT_Int32  b )
   {
-    register FT_Int32  result;
+    FT_Int32  result;
 
 
     __asm__ __volatile__ (
@@ -152,7 +152,7 @@
   FT_MulFix_i386( FT_Int32  a,
                   FT_Int32  b )
   {
-    register FT_Int32  result;
+    FT_Int32  result;
 
     __asm
     {
@@ -300,6 +300,18 @@
 
 
   /*
+   *  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
@@ -400,7 +412,7 @@
 
 FT_END_HEADER
 
-#endif /* __FTCALC_H__ */
+#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 216c730..d110457 100644
--- a/include/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -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 16856d3..902f02f 100644
--- a/include/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType font driver interface (specification).                      */
 /*                                                                         */
-/*  Copyright 1996-2015 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 85%
rename from include/internal/ftgloadr.h
rename to include/freetype/internal/ftgloadr.h
index 970dd70..bebf5db 100644
--- a/include/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph loader (specification).                           */
 /*                                                                         */
-/*  Copyright 2002-2015 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 */
@@ -166,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 96%
rename from include/internal/ftmemory.h
rename to include/freetype/internal/ftmemory.h
index c0c553b..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-2015 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), \
@@ -380,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 97%
rename from include/internal/ftobjs.h
rename to include/freetype/internal/ftobjs.h
index 37317a4..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-2015 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
@@ -83,12 +83,12 @@
             x > y ? x + ( 3 * y >> 3 )   \
                   : y + ( 3 * x >> 3 ) )
 
-  /* we use the TYPEOF macro to suppress signedness compilation warnings */
-#define FT_PAD_FLOOR( x, n )  ( (x) & ~TYPEOF( 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) & ~TYPEOF( 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 )
 
@@ -341,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        */
@@ -365,7 +359,6 @@
     FT_Incremental_InterfaceRec*  incremental_interface;
 #endif
 
-    FT_Bool             ignore_unpatented_hinter;
     FT_Int              refcount;
 
   } FT_Face_InternalRec;
@@ -506,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 )
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -536,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
+
   /* */
 
 
@@ -772,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 );
@@ -844,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.              */
@@ -982,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).                                                          */
@@ -1041,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).                                                          */
@@ -1101,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).                                                          */
@@ -1175,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'.                                         */
   /*                                                                       */
@@ -1379,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'.                                         */
   /*                                                                       */
@@ -1565,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 7f9154f..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-2015 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 98%
rename from include/internal/ftrfork.h
rename to include/freetype/internal/ftrfork.h
index da61ca7..b923401 100644
--- a/include/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (specification).                    */
 /*                                                                         */
-/*  Copyright 2004-2015 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>
@@ -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 8f837e4..9189717 100644
--- a/include/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType services (specification only).                          */
 /*                                                                         */
-/*  Copyright 2003-2015 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_FONT_FORMAT_H        <internal/services/svfntfmt.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 99%
rename from include/internal/ftstream.h
rename to include/freetype/internal/ftstream.h
index 384e5df..6d04875 100644
--- a/include/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Stream handling (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -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 9d28d21..efb3355 100644
--- a/include/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tracing handling (specification only).                               */
 /*                                                                         */
-/*  Copyright 2002-2015 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 97%
rename from include/internal/ftvalid.h
rename to include/freetype/internal/ftvalid.h
index 9cda6ee..aac92c9 100644
--- a/include/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType validation support (specification).                         */
 /*                                                                         */
-/*  Copyright 2004-2015 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 */
@@ -153,7 +153,7 @@
 
 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 1c1fd0e..8c3c14c 100644
--- a/include/internal/internal.h
+++ b/include/freetype/internal/internal.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Internal header files (specification only).                          */
 /*                                                                         */
-/*  Copyright 1996-2015 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 99%
rename from include/internal/psaux.h
rename to include/freetype/internal/psaux.h
index 1c5f784..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-2015 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
 
 
@@ -678,6 +679,7 @@
     FT_Int               num_subrs;
     FT_Byte**            subrs;
     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 99%
rename from include/internal/pshints.h
rename to include/freetype/internal/pshints.h
index 12aaaba..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-2015 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>
@@ -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 865b536..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-2015 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 96%
rename from include/internal/services/svcid.h
rename to include/freetype/internal/services/svcid.h
index 4a535a6..dbbe604 100644
--- a/include/internal/services/svcid.h
+++ b/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType CID font services (specification).                      */
 /*                                                                         */
-/*  Copyright 2007-2015 by                                                 */
+/*  Copyright 2007-2016 by                                                 */
 /*  Derek Clegg and Michael Toftdal.                                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __SVCID_H__
-#define __SVCID_H__
+#ifndef SVCID_H_
+#define SVCID_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -84,7 +84,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVCID_H__ */
+#endif /* SVCID_H_ */
 
 
 /* END */
diff --git a/include/internal/services/svfntfmt.h b/include/freetype/internal/services/svfntfmt.h
similarity index 92%
rename from include/internal/services/svfntfmt.h
rename to include/freetype/internal/services/svfntfmt.h
index f8b3617..bd295c9 100644
--- a/include/internal/services/svfntfmt.h
+++ b/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType font format service (specification only).               */
 /*                                                                         */
-/*  Copyright 2003-2015 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 __SVFNTFMT_H__
-#define __SVFNTFMT_H__
+#ifndef SVFNTFMT_H_
+#define SVFNTFMT_H_
 
 #include FT_INTERNAL_SERVICE_H
 
@@ -49,7 +49,7 @@
 FT_END_HEADER
 
 
-#endif /* __SVFNTFMT_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 f78bca5..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-2015 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 59cc3b7..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-2015 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 bc26f15..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-2015 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 f2cecfb..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-2015 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 a82a642..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-2015 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 d4eb169..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-2015 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 a89f79e..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-2015 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 c9f07ce..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-2015 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 66da6e1..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-2015 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 752a266..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-2015 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 252ae1c..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-2015 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 92%
rename from include/internal/services/svttcmap.h
rename to include/freetype/internal/services/svttcmap.h
index 4351a9a..772c721 100644
--- a/include/internal/services/svttcmap.h
+++ b/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType TrueType/sfnt cmap extra information service.           */
 /*                                                                         */
-/*  Copyright 2003-2015 by                                                 */
+/*  Copyright 2003-2016 by                                                 */
 /*  Masatake YAMATO, Redhat K.K.,                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
@@ -19,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
@@ -48,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_
   {
@@ -99,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 272ee8c..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-2015 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 94%
rename from include/internal/services/svttglyf.h
rename to include/freetype/internal/services/svttglyf.h
index f5cb76a..c33edd4 100644
--- a/include/internal/services/svttglyf.h
+++ b/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType TrueType glyph service.                                 */
 /*                                                                         */
-/*  Copyright 2007-2015 by                                                 */
+/*  Copyright 2007-2016 by                                                 */
 /*  David Turner.                                                          */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -15,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
@@ -63,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 0036929..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-2015 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 93%
rename from include/internal/sfnt.h
rename to include/freetype/internal/sfnt.h
index 97ce390..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-2015 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.                 */
   /*                                                                       */
@@ -427,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>                                                         */
@@ -556,6 +587,8 @@
 
     TT_Get_Metrics_Func          get_metrics;
 
+    TT_Get_Name_Func             get_name;
+
   } SFNT_Interface;
 
 
@@ -594,7 +627,8 @@
           free_eblc_,                    \
           set_sbit_strike_,              \
           load_strike_metrics_,          \
-          get_metrics_ )                 \
+          get_metrics_,                  \
+          get_name_ )                    \
   static const SFNT_Interface  class_ =  \
   {                                      \
     goto_table_,                         \
@@ -626,6 +660,7 @@
     set_sbit_strike_,                    \
     load_strike_metrics_,                \
     get_metrics_,                        \
+    get_name_,                           \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
@@ -663,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 )    \
@@ -699,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 97%
rename from include/internal/t1types.h
rename to include/freetype/internal/t1types.h
index 029acc4..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-2015 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
 
 
@@ -107,6 +108,7 @@
     FT_Int           num_subrs;
     FT_Byte**        subrs;
     FT_UInt*         subrs_len;
+    FT_Hash          subrs_hash;
 
     FT_Int           num_glyphs;
     FT_String**      glyph_names;       /* array of glyph names       */
@@ -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 98%
rename from include/internal/tttypes.h
rename to include/freetype/internal/tttypes.h
index 31dd0aa..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-2015 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.      */
   /*                                                                       */
@@ -1233,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).           */
   /*                                                                       */
@@ -1334,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
 
     /***********************************************************************/
     /*                                                                     */
@@ -1378,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;
@@ -1393,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;
 
@@ -1457,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;
 
@@ -1503,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 99%
rename from include/t1tables.h
rename to include/freetype/t1tables.h
index a6ea415..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-2015 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>
@@ -755,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 99%
rename from include/ttnameid.h
rename to include/freetype/ttnameid.h
index c9585f2..ce707f1 100644
--- a/include/ttnameid.h
+++ b/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType name ID definitions (specification only).                   */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -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 99%
rename from include/tttables.h
rename to include/freetype/tttables.h
index 1568f40..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-2015 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>
@@ -587,7 +587,7 @@
   /*                                                                       */
   /*    FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure.     */
   /*                                                                       */
-  /*    FT_SFNT_VHEA :: To access the font's @TT_VertHeader struture.      */
+  /*    FT_SFNT_VHEA :: To access the font's @TT_VertHeader structure.     */
   /*                                                                       */
   /*    FT_SFNT_POST :: To access the font's @TT_Postscript structure.     */
   /*                                                                       */
@@ -823,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 3836c7b..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-2015 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 8ea5568..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-2015 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,9 +42,11 @@
   *   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' )
@@ -54,7 +57,7 @@
 FT_END_HEADER
 
 
-#endif /* __TTUNPAT_H__ */
+#endif /* TTUNPAT_H_ */
 
 
 /* END */
diff --git a/include/ft2build.h b/include/ft2build.h
index 09c19d4..c89cb46 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType 2 build and setup macros.                                   */
 /*                                                                         */
-/*  Copyright 1996-2015 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 376bee6..0000000
--- a/include/fterrors.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  fterrors.h                                                             */
-/*                                                                         */
-/*    FreeType error code handling (specification).                        */
-/*                                                                         */
-/*  Copyright 1996-2015 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 4cd999a..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-2015 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 f56040b..0000000
--- a/include/ftttdrv.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftttdrv.h                                                              */
-/*                                                                         */
-/*    FreeType API for controlling the TrueType driver                     */
-/*    (specification only).                                                */
-/*                                                                         */
-/*  Copyright 2013-2015 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 (except if `native
-   *   ClearType' is selected by the font).  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 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).
-   *
-   *   FreeType doesn't provide all capabilities of the most recent
-   *   ClearType incarnation, thus we identify our subpixel support as
-   *   version~38.
-   *
-   */
-#define TT_INTERPRETER_VERSION_35  35
-#define TT_INTERPRETER_VERSION_38  38
-
- /* */
-
-
-FT_END_HEADER
-
-
-#endif /* __FTTTDRV_H__ */
-
-
-/* END */
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index 1b1eb31..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-2015 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,       */
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
index e2b2451..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-2015 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,107 +26,249 @@
   af_blue_strings[] =
   {
     /* */
-    '\xD8', '\xA7', '\xD8', '\xA5', '\xD9', '\x84', '\xD9', '\x83', '\xD8', '\xB7', '\xD8', '\xB8',  /* ا إ ل ك ط ظ */
+    '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8',  /* ا إ ل ك ط ظ */
     '\0',
-    '\xD8', '\xAA', '\xD8', '\xAB', '\xD8', '\xB7', '\xD8', '\xB8', '\xD9', '\x83',  /* ت ث ط ظ ك */
+    '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83',  /* ت ث ط ظ ك */
     '\0',
-    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕПЗОСЭ */
+    '\xD9', '\x80',  /* ـ */
     '\0',
-    '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD',  /* БВЕШЗОСЭ */
+    '\xD4', '\xB1', ' ', '\xD5', '\x84', ' ', '\xD5', '\x92', ' ', '\xD5', '\x8D', ' ', '\xD4', '\xB2', ' ', '\xD4', '\xB3', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x95',  /* Ա Մ Ւ Ս Բ Գ Դ Օ */
     '\0',
-    '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81',  /* хпншезос */
+    '\xD5', '\x92', ' ', '\xD5', '\x88', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x83', ' ', '\xD5', '\x87', ' ', '\xD5', '\x8D', ' ', '\xD5', '\x8F', ' ', '\xD5', '\x95',  /* Ւ Ո Դ Ճ Շ Ս Տ Օ */
     '\0',
-    '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84',  /* руф */
+    '\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', '\xA4', '\x88', '\xE0', '\xA4', '\x90', '\xE0', '\xA4', '\x93', '\xE0', '\xA4', '\x94', '\xE0', '\xA4', '\xBF', '\xE0', '\xA5', '\x80', '\xE0', '\xA5', '\x8B', '\xE0', '\xA5', '\x8C',  /* ई ऐ ओ औ ि ी ो ौ */
+    '\xD5', '\xB0', ' ', '\xD5', '\xB8', ' ', '\xD5', '\xB3', ' ', '\xD5', '\xA1', ' ', '\xD5', '\xA5', ' ', '\xD5', '\xAE', ' ', '\xD5', '\xBD', ' ', '\xD6', '\x85',  /* հ ո ճ ա ե ծ ս օ */
     '\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', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81',  /* բ ը ի լ ղ պ փ ց */
     '\0',
-    '\xE0', '\xA5', '\x81', '\xE0', '\xA5', '\x83',  /* ु ृ */
+    '\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', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9',  /* ΓΒΕΖΘΟΩ */
+    '\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97',  /* ই ট ঠ ি ী ৈ ৗ */
     '\0',
-    '\xCE', '\x92', '\xCE', '\x94', '\xCE', '\x96', '\xCE', '\x9E', '\xCE', '\x98', '\xCE', '\x9F',  /* ΒΔΖΞΘΟ */
+    '\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', '\xB8', '\xCE', '\xB4', '\xCE', '\xB6', '\xCE', '\xBB', '\xCE', '\xBE',  /* βθδζλξ */
+    '\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',
-    '\xCE', '\xB1', '\xCE', '\xB5', '\xCE', '\xB9', '\xCE', '\xBF', '\xCF', '\x80', '\xCF', '\x83', '\xCF', '\x84', '\xCF', '\x89',  /* αειοπστω */
+    '\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',
-    '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88',  /* βγημρφχψ */
+    '\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', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1',  /* בדהחךכםס */
+    '\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB',  /* ᏸ ꮐ ꭹ ꭻ */
     '\0',
-    '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6',  /* בטכםסצ */
+    '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е П З О С Э */
     '\0',
-    '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5',  /* קךןףץ */
+    '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е Ш З О С Э */
     '\0',
-    'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S',  /* THEZOCQS */
+    '\xD1', '\x85', ' ', '\xD0', '\xBF', ' ', '\xD0', '\xBD', ' ', '\xD1', '\x88', ' ', '\xD0', '\xB5', ' ', '\xD0', '\xB7', ' ', '\xD0', '\xBE', ' ', '\xD1', '\x81',  /* х п н ш е з о с */
     '\0',
-    'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S',  /* HEZLOCUS */
+    '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84',  /* р у ф */
     '\0',
-    'f', 'i', 'j', 'k', 'd', 'b', 'h',  /* fijkdbh */
+    '\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',
-    'x', 'z', 'r', 'o', 'e', 's', 'c',  /* xzroesc */
+    '\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',
-    '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', '\xB0', '\x87', '\xE0', '\xB0', '\x8C', '\xE0', '\xB0', '\x99', '\xE0', '\xB0', '\x9E', '\xE0', '\xB0', '\xA3', '\xE0', '\xB0', '\xB1', '\xE0', '\xB1', '\xAF',  /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
+    '\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83',  /* ु ृ */
     '\0',
-    '\xE0', '\xB0', '\x85', '\xE0', '\xB0', '\x95', '\xE0', '\xB0', '\x9A', '\xE0', '\xB0', '\xB0', '\xE0', '\xB0', '\xBD', '\xE0', '\xB1', '\xA8', '\xE0', '\xB1', '\xAC',  /* అ క చ ర ఽ ౨ ౬ */
+    '\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',
-    '\xE0', '\xB8', '\x9A', '\xE0', '\xB9', '\x80', '\xE0', '\xB9', '\x81', '\xE0', '\xB8', '\xAD', '\xE0', '\xB8', '\x81', '\xE0', '\xB8', '\xB2',  /* บ เ แ อ ก า */
+    '\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',
-    '\xE0', '\xB8', '\x9A', '\xE0', '\xB8', '\x9B', '\xE0', '\xB8', '\xA9', '\xE0', '\xB8', '\xAF', '\xE0', '\xB8', '\xAD', '\xE0', '\xB8', '\xA2', '\xE0', '\xB8', '\xAE',  /* บ ป ษ ฯ อ ย ฮ */
+    '\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',
-    '\xE0', '\xB8', '\x9B', '\xE0', '\xB8', '\x9D', '\xE0', '\xB8', '\x9F',  /* ป ฝ ฟ */
+    '\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',
-    '\xE0', '\xB9', '\x82', '\xE0', '\xB9', '\x83', '\xE0', '\xB9', '\x84',  /* โ ใ ไ */
+    '\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',
-    '\xE0', '\xB8', '\x8E', '\xE0', '\xB8', '\x8F', '\xE0', '\xB8', '\xA4', '\xE0', '\xB8', '\xA6',  /* ฎ ฏ ฤ ฦ */
+    '\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',
-    '\xE0', '\xB8', '\x8D', '\xE0', '\xB8', '\x90',  /* ญ ฐ */
+    '\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',
-    '\xE0', '\xB9', '\x90', '\xE0', '\xB9', '\x91', '\xE0', '\xB9', '\x93',  /* ๐ ๑ ๓ */
+    '\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',
@@ -139,9 +281,33 @@
   af_blue_stringsets[] =
   {
     /* */
-    { AF_BLUE_STRING_ARABIC_TOP,   AF_BLUE_PROPERTY_LATIN_TOP },
-    { AF_BLUE_STRING_ARABIC_JOIN,  0                          },
-    { AF_BLUE_STRING_MAX,          0                          },
+    { 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      |
@@ -157,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        },
@@ -165,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        },
@@ -178,6 +397,39 @@
     { 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                          },
diff --git a/src/autofit/afblue.cin b/src/autofit/afblue.cin
index b303a4b..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-2015 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 fd5684e..f5f04f2 100644
--- a/src/autofit/afblue.dat
+++ b/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
 //
 //    Auto-fitter data for blue strings.
 //
-//  Copyright 2013-2015 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.
 
 
@@ -69,20 +76,54 @@
 
   AF_BLUE_STRING_ARABIC_TOP
     "ا إ ل ك ط ظ"
-  AF_BLUE_STRING_ARABIC_JOIN
+  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
+    "ـ"
+
+  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
-    "руф"
+    "р у ф"
 
-  // we separate the letters with spaces to avoid ligatures;
-  // this is just for convenience to simplify reading
   AF_BLUE_STRING_DEVANAGARI_BASE
     "क म अ आ थ ध भ श"
   AF_BLUE_STRING_DEVANAGARI_TOP
@@ -95,37 +136,168 @@
   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 separate the letters with spaces to avoid ligatures;
-  // this is just for convenience to simplify reading
+  // 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
@@ -150,44 +322,44 @@
 #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 */
 
@@ -219,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.
 //
@@ -229,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
@@ -264,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.
@@ -289,9 +484,39 @@
 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_JOIN,  0                          }
-    { AF_BLUE_STRING_MAX,          0                          }
+    { 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        }
@@ -312,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                                 }
@@ -322,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   }
@@ -329,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                                 }
@@ -339,6 +636,53 @@
     { 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                          }
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
index 94e33a9..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-2015 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 )
 
 
   /*************************************************************************/
@@ -75,46 +78,117 @@
   typedef enum  AF_Blue_String_
   {
     AF_BLUE_STRING_ARABIC_TOP = 0,
-    AF_BLUE_STRING_ARABIC_JOIN = 13,
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 24,
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 41,
-    AF_BLUE_STRING_CYRILLIC_SMALL = 58,
-    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 75,
-    AF_BLUE_STRING_DEVANAGARI_BASE = 82,
-    AF_BLUE_STRING_DEVANAGARI_TOP = 107,
-    AF_BLUE_STRING_DEVANAGARI_HEAD = 132,
-    AF_BLUE_STRING_DEVANAGARI_BOTTOM = 157,
-    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 164,
-    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 179,
-    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 192,
-    AF_BLUE_STRING_GREEK_SMALL = 205,
-    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 222,
-    AF_BLUE_STRING_HEBREW_TOP = 239,
-    AF_BLUE_STRING_HEBREW_BOTTOM = 256,
-    AF_BLUE_STRING_HEBREW_DESCENDER = 269,
-    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 280,
-    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 289,
-    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 298,
-    AF_BLUE_STRING_LATIN_SMALL = 306,
-    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 314,
-    AF_BLUE_STRING_TELUGU_TOP = 320,
-    AF_BLUE_STRING_TELUGU_BOTTOM = 342,
-    AF_BLUE_STRING_THAI_TOP = 364,
-    AF_BLUE_STRING_THAI_BOTTOM = 383,
-    AF_BLUE_STRING_THAI_ASCENDER = 405,
-    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 415,
-    AF_BLUE_STRING_THAI_DESCENDER = 425,
-    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 438,
-    AF_BLUE_STRING_THAI_DIGIT_TOP = 445,
-    af_blue_1_1 = 454,
+    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 */
@@ -148,9 +222,10 @@
   /* blue string can't be used in more than a single writing system, which */
   /* is a safe bet.                                                        */
 #define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 3 )
+#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    ( 1U << 0 )       /* must have value 1 */
 #define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
@@ -165,14 +240,33 @@
   typedef enum  AF_Blue_Stringset_
   {
     AF_BLUE_STRINGSET_ARAB = 0,
-    AF_BLUE_STRINGSET_CYRL = 3,
-    AF_BLUE_STRINGSET_DEVA = 9,
-    AF_BLUE_STRINGSET_GREK = 15,
-    AF_BLUE_STRINGSET_HEBR = 22,
-    AF_BLUE_STRINGSET_LATN = 26,
-    AF_BLUE_STRINGSET_TELU = 33,
-    AF_BLUE_STRINGSET_THAI = 36,
-    af_blue_2_1 = 44,
+    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,
@@ -208,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 ad43fe6..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-2015 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 )
 
 
   /*************************************************************************/
@@ -97,9 +100,10 @@
   /* blue string can't be used in more than a single writing system, which */
   /* is a safe bet.                                                        */
 #define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 3 )
+#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    ( 1U << 0 )       /* must have value 1 */
 #define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
@@ -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 905408b..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-2015 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,
@@ -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;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -889,15 +966,12 @@
 
       if ( seg2 )
       {
-        seg2->num_linked++;
         if ( seg2->link != seg1 )
         {
           seg1->link = NULL;
 
           if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )
             seg1->serif = seg2->link;
-          else
-            seg2->num_linked--;
         }
       }
     }
@@ -1014,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;
@@ -1451,7 +1525,7 @@
       }
 
       if ( dist < 54 )
-        dist += ( 54 - dist ) / 2 ;
+        dist += ( 54 - dist ) / 2;
       else if ( dist < 3 * 64 )
       {
         FT_Pos  delta;
@@ -2181,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 )
   {
@@ -2189,6 +2264,7 @@
     int       dim;
 
     FT_UNUSED( metrics );
+    FT_UNUSED( glyph_index );
 
 
     error = af_glyph_hints_reload( hints, outline );
@@ -2278,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
@@ -2297,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 bfd11f2..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-2015 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"
@@ -115,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 );
 
@@ -134,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 520e8a4..1c39a70 100644
--- a/src/autofit/afcover.h
+++ b/src/autofit/afcover.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter coverages (specification only).                          */
 /*                                                                         */
-/*  Copyright 2013-2015 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 03ca25f..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-2015 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 b4fdc78..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-2015 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 7b416e4..53c01f6 100644
--- a/src/autofit/aferrors.h
+++ b/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Autofitter error codes (specification only).                         */
 /*                                                                         */
-/*  Copyright 2005-2015 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 64b9293..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-2015 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,18 +344,28 @@
 
     memory = face->memory;
 
+    /* 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_Byte ) ) )
+                     (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 );
@@ -372,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 9bbb687..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-2015 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 37482eb..0f7f6e5 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (body).                                 */
 /*                                                                         */
-/*  Copyright 2003-2015 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,       */
@@ -99,6 +99,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      *anedge )
   {
@@ -153,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 */
@@ -219,6 +221,82 @@
 #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
   extern "C" {
 #endif
@@ -226,30 +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" ));
 
     if ( hints->num_points )
-      AF_DUMP(( "  [ index |  xorg |  yorg | xscale | yscale"
-                " |  xfit |  yfit |  flags ]\n" ));
+      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 ]\n",
-                AF_INDEX_NUM( 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->y / 64.0 ));
+    }
     AF_DUMP(( "\n" ));
   }
 #ifdef __cplusplus
@@ -306,31 +413,34 @@
       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",
+        AF_DUMP(( "  %5d  %5d  %5d  %5s  %4d  %4d"
+                  "  %4s  %5s  %4s"
+                  "  %6d  %5d  %11s\n",
                   AF_INDEX_NUM( seg, segments ),
-                  dimension == AF_DIMENSION_HORZ
-                               ? (int)seg->first->ox / 64.0
-                               : (int)seg->first->oy / 64.0,
+                  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( seg->flags ) ));
@@ -435,28 +545,39 @@
       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",
+        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,
@@ -702,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;
 
@@ -722,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:
@@ -734,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;
@@ -742,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;
             }
           }
         }
@@ -769,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;
@@ -826,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
@@ -849,7 +986,7 @@
 
 
             point = next;
-            next = point->next;
+            next  = point->next;
 
             out_x += next->fx - point->fx;
             out_y += next->fy - point->fy;
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index a64c7a4..4fdf732 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (specification).                        */
 /*                                                                         */
-/*  Copyright 2003-2015 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"
 
@@ -221,6 +221,9 @@
   /* candidates for weak interpolation have this flag set */
 #define AF_FLAG_WEAK_INTERPOLATION  ( 1U << 4 )
 
+  /* the distance to the next point is very small */
+#define AF_FLAG_NEAR  ( 1U << 5 )
+
 
   /* edge hint flags */
 #define AF_EDGE_NORMAL  0
@@ -257,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           */
@@ -266,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  */
 
@@ -289,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 */
@@ -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 7412cd1..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-2015 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 4c36908..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-2015 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 893e986..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-2015 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 )
@@ -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,394 +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;
-        /* reject glyphs that don't produce any rendering */
-        if ( error || outline.n_points <= 2 )
+        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 (usable) 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 )
       {
@@ -775,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;
@@ -785,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;
 
@@ -802,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" ));
 
@@ -816,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 )
@@ -854,6 +987,8 @@
       }
     }
 
+    af_shaper_buf_destroy( face, shaper_buf );
+
     metrics->root.digits_have_same_width = same_width;
   }
 
@@ -941,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;
@@ -967,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
           }
         }
       }
@@ -1032,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++ )
@@ -1106,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
     }
   }
 
@@ -1140,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;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -1155,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 );
@@ -1203,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 )
@@ -1243,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 */
           }
         }
@@ -1289,7 +1683,12 @@
           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;
@@ -1301,12 +1700,46 @@
           /* clear all segment fields */
           segment[0] = seg0;
 
-          segment->dir      = (FT_Char)segment_dir;
-          min_pos = max_pos = point->u;
-          segment->first    = point;
-          segment->last     = point;
+          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;
@@ -1518,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;
@@ -1528,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;
@@ -1540,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 );
 
     /*********************************************************************/
     /*                                                                   */
@@ -1581,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 */
@@ -1617,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;
@@ -1642,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;
+      }
+    }
+
 
     /******************************************************************/
     /*                                                                */
@@ -1872,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 =
@@ -2081,6 +2574,7 @@
   af_latin_compute_stem_width( AF_GlyphHints  hints,
                                AF_Dimension   dim,
                                FT_Pos         width,
+                               FT_Pos         base_delta,
                                FT_UInt        base_flags,
                                FT_UInt        stem_flags )
   {
@@ -2158,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
@@ -2247,11 +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,
-                                                        base_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;
@@ -2302,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
 
 
@@ -2311,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            */
 
@@ -2446,7 +2987,8 @@
 
 
         org_len = edge2->opos - edge->opos;
-        cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
                                                edge->flags,
                                                edge2->flags );
 
@@ -2515,7 +3057,8 @@
         org_len    = edge2->opos - edge->opos;
         org_center = org_pos + ( org_len >> 1 );
 
-        cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
                                                edge->flags,
                                                edge2->flags );
 
@@ -2575,7 +3118,8 @@
           org_len    = edge2->opos - edge->opos;
           org_center = org_pos + ( org_len >> 1 );
 
-          cur_len    = af_latin_compute_stem_width( hints, dim, org_len,
+          cur_len    = af_latin_compute_stem_width( hints, dim,
+                                                    org_len, 0,
                                                     edge->flags,
                                                     edge2->flags );
 
@@ -2606,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;
+          }
         }
       }
     }
@@ -2767,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;
+          }
         }
       }
     }
@@ -2805,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 )
   {
@@ -2847,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 */
@@ -2907,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 6855492..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-2015 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 ) \
@@ -65,8 +67,10 @@
 
 #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_NEUTRAL     ( 1U << 2 ) /* we have neutral blue zone */
-#define AF_LATIN_BLUE_ADJUSTMENT  ( 1U << 3 ) /* used for scale adjustment */
+#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              */
 
 
@@ -74,6 +78,8 @@
   {
     AF_WidthRec  ref;
     AF_WidthRec  shoot;
+    FT_Pos       ascender;
+    FT_Pos       descender;
     FT_UInt      flags;
 
   } AF_LatinBlueRec, *AF_LatinBlue;
@@ -182,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 ac9f933..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-2015 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;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
@@ -1179,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;
@@ -2300,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 )
@@ -2389,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 9326753..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-2015 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 7c2fa7c..26bba06 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (body).                           */
 /*                                                                         */
-/*  Copyright 2003-2015 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,6 +23,8 @@
 #include "afmodule.h"
 #include "afpic.h"
 
+#include FT_INTERNAL_CALC_H
+
 
   /* Initialize glyph loader. */
 
@@ -76,6 +78,14 @@
   }
 
 
+#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. */
@@ -88,6 +98,8 @@
                     FT_UInt    glyph_index,
                     FT_Int32   load_flags )
   {
+    AF_Module  module = loader->globals->module;
+
     FT_Error          error;
     FT_Face           face     = loader->face;
     AF_StyleMetrics   metrics  = loader->metrics;
@@ -103,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 )
     {
@@ -150,7 +288,8 @@
 
 
         if ( writing_system_class->style_hints_apply )
-          writing_system_class->style_hints_apply( hints,
+          writing_system_class->style_hints_apply( glyph_index,
+                                                   hints,
                                                    &gloader->base.outline,
                                                    metrics );
       }
@@ -404,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 37cfd14..0062eb9 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (specification).                  */
 /*                                                                         */
-/*  Copyright 2003-2015 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 __AFLOADER_H__
-#define __AFLOADER_H__
+#ifndef AFLOADER_H_
+#define AFLOADER_H_
 
 #include "afhints.h"
 #include "afmodule.h"
@@ -75,12 +75,17 @@
                         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 8ae425c..e8f8ff4 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (body).                            */
 /*                                                                         */
-/*  Copyright 2003-2015 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,       */
@@ -25,6 +25,10 @@
 #ifdef FT_DEBUG_AUTOFIT
 
 #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 );
@@ -34,6 +38,10 @@
   extern void
   af_glyph_hints_dump_edges( AF_GlyphHints  hints,
                              FT_Bool        to_stdout );
+#ifdef __cplusplus
+  }
+#endif
+
 #endif
 
   int  _af_debug_disable_horz_hints;
@@ -99,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  */
@@ -139,19 +158,33 @@
     }
     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;
@@ -161,14 +194,121 @@
 #ifdef AF_CONFIG_OPTION_USE_WARPER
     else if ( !ft_strcmp( property_name, "warping" ) )
     {
-      FT_Bool*  warping = (FT_Bool*)value;
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+      if ( value_is_string )
+      {
+        const char*  s = (const char*)value;
+        long         w = ft_strtol( s, NULL, 10 );
 
 
-      module->warping = *warping;
+        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 ));
@@ -245,6 +385,33 @@
       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 ));
@@ -254,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(
@@ -291,11 +458,21 @@
     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;
+    module->warping           = 0;
 #endif
+    module->no_stem_darkening = TRUE;
+
+    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;
   }
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index b9c2fd8..e65db5f 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (specification).                   */
 /*                                                                         */
-/*  Copyright 2003-2015 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 __AFMODULE_H__
-#define __AFMODULE_H__
+#ifndef AFMODULE_H_
+#define AFMODULE_H_
 
 #include <ft2build.h>
 #include FT_INTERNAL_OBJECTS_H
@@ -41,6 +41,8 @@
 #ifdef AF_CONFIG_OPTION_USE_WARPER
     FT_Bool       warping;
 #endif
+    FT_Bool       no_stem_darkening;
+    FT_Int        darken_params[8];
 
   } AF_ModuleRec, *AF_Module;
 
@@ -50,7 +52,7 @@
 
 FT_END_HEADER
 
-#endif /* __AFMODULE_H__ */
+#endif /* AFMODULE_H_ */
 
 
 /* END */
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 5589e61..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-2015 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 25071e3..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-2015 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 c1e0afb..732f3d1 100644
--- a/src/autofit/afranges.c
+++ b/src/autofit/afranges.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter Unicode script ranges (body).                            */
 /*                                                                         */
-/*  Copyright 2013-2015 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,175 +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.
+   *
+   */
+
+
+  /* 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(  0x0600UL,  0x06FFUL ),  /* Arabic                                 */
-    AF_UNIRANGE_REC(  0x0750UL,  0x07FFUL ),  /* Arabic Supplement                      */
-    AF_UNIRANGE_REC(  0x08A0UL,  0x08FFUL ),  /* Arabic Extended-A                      */
-    AF_UNIRANGE_REC(  0xFB50UL,  0xFDFFUL ),  /* Arabic Presentation Forms-A            */
-    AF_UNIRANGE_REC(  0xFE70UL,  0xFEFFUL ),  /* Arabic Presentation Forms-B            */
-    AF_UNIRANGE_REC( 0x1EE00UL, 0x1EEFFUL ),  /* Arabic Mathematical Alphabetic Symbols */
-    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_cyrl_uniranges[] =
+  const AF_Script_UniRangeRec  af_arab_nonbase_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,  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 )
   };
 
-  /* 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[] =
+  const AF_Script_UniRangeRec  af_armn_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0900UL,  0x093BUL ),  /* Devanagari       */
-    /* omitting U+093C nukta */
-    AF_UNIRANGE_REC(  0x093DUL,  0x0950UL ),
-    /* omitting U+0951 udatta, U+0952 anudatta */
-    AF_UNIRANGE_REC(  0x0953UL,  0x0963UL ),
-    /* omitting U+0964 danda, U+0965 double danda */
-    AF_UNIRANGE_REC(  0x0966UL,  0x097FUL ),
-    AF_UNIRANGE_REC(  0x20B9UL,  0x20B9UL ),  /* (new) Rupee sign */
-    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_grek_uniranges[] =
+  const AF_Script_UniRangeRec  af_armn_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
-    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended   */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0559,  0x055F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_hebr_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0590UL,  0x05FFUL ),  /* Hebrew                          */
-    AF_UNIRANGE_REC(  0xFB1DUL,  0xFB4FUL ),  /* Alphab. Present. Forms (Hebrew) */
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-  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 )
-  };
-
-  const AF_Script_UniRangeRec  af_telu_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0C00UL,  0x0C7FUL ),  /* Telugu */
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-  const AF_Script_UniRangeRec  af_thai_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0E00UL,  0x0E7FUL ),  /* Thai */
-    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(  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 */
@@ -197,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 7c78ab0..1a0e4b1 100644
--- a/src/autofit/afranges.h
+++ b/src/autofit/afranges.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter Unicode script ranges (specification).                   */
 /*                                                                         */
-/*  Copyright 2013-2015 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 dfcc830..cffe591 100644
--- a/src/autofit/afscript.h
+++ b/src/autofit/afscript.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter scripts (specification only).                            */
 /*                                                                         */
-/*  Copyright 2013-2015 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,114 +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,
-          0x644, 0x62D, 0x640 ) /* ل ح ـ */
+          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 ) /* οΟ */
+          HINTING_BOTTOM_TO_TOP,
+          "\xCE\xBF \xCE\x9F" ) /* ο Ο */
+
+  SCRIPT( gujr, GUJR,
+          "Gujarati",
+          HB_SCRIPT_GUJARATI,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xAA\x9F \xE0\xAB\xA6" ) /* ટ ૦ */
+
+  SCRIPT( guru, GURU,
+          "Gurmukhi",
+          HB_SCRIPT_GURMUKHI,
+          HINTING_TOP_TO_BOTTOM,
+          "\xE0\xA8\xA0 \xE0\xA8\xB0 \xE0\xA9\xA6" ) /* ਠ ਰ ੦ */
 
   SCRIPT( hebr, HEBR,
           "Hebrew",
           HB_SCRIPT_HEBREW,
-          0x5DD, 0x0, 0x0 ) /* ם */
+          HINTING_BOTTOM_TO_TOP,
+          "\xD7\x9D" ) /* ם */
+
+  SCRIPT( knda, KNDA,
+          "Kannada",
+          HB_SCRIPT_KANNADA,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */
+
+  /* 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,
-          'o', 'O', '0' )
+          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,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB4\xA0 \xE0\xB4\xB1" ) /* ഠ റ */
+
+  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,
-          0x0, 0x0, 0x0 )
+          HINTING_BOTTOM_TO_TOP,
+          "" )
+
+  SCRIPT( sinh, SINH,
+          "Sinhala",
+          HB_SCRIPT_SINHALA,
+          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,
-          0xC66, 0xC67, 0x0 ) /* ౦ ౧ */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */
 
   SCRIPT( thai, THAI,
           "Thai",
           HB_SCRIPT_THAI,
-          0xE32, 0xE45, 0xE50 ) /* า ๅ ๐ */
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */
 
 #ifdef AF_CONFIG_OPTION_INDIC
 
-  SCRIPT( beng, BENG,
-          "Bengali",
-          HB_SCRIPT_BENGALI,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( gujr, GUJR,
-          "Gujarati",
-          HB_SCRIPT_GUJARATI,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( guru, GURU,
-          "Gurmukhi",
-          HB_SCRIPT_GURMUKHI,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( knda, KNDA,
-          "Kannada",
-          HB_SCRIPT_KANNADA,
-          'o', 0x0, 0x0 ) /* XXX */
-
   SCRIPT( limb, LIMB,
           "Limbu",
           HB_SCRIPT_LIMBU,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( mlym, MLYM,
-          "Malayalam",
-          HB_SCRIPT_MALAYALAM,
-          'o', 0x0, 0x0 ) /* XXX */
+          HINTING_BOTTOM_TO_TOP,
+          "o" ) /* XXX */
 
   SCRIPT( orya, ORYA,
           "Oriya",
           HB_SCRIPT_ORIYA,
-          'o', 0x0, 0x0 ) /* XXX */
-
-  SCRIPT( sinh, SINH,
-          "Sinhala",
-          HB_SCRIPT_SINHALA,
-          'o', 0x0, 0x0 ) /* XXX */
+          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 */
+          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 */
 
@@ -141,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 68%
rename from src/autofit/hbshim.c
rename to src/autofit/afshaper.c
index c9c1db0..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-2015 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;
     }
@@ -363,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(( "*" ));
@@ -418,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_Int  upem = (FT_Int)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;
   }
 
 
@@ -507,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 bfd5bb9..e83a95b 100644
--- a/src/autofit/afstyles.h
+++ b/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter styles (specification only).                             */
 /*                                                                         */
-/*  Copyright 2013-2015 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",                       \
@@ -88,23 +90,122 @@
          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
@@ -116,11 +217,39 @@
          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,
@@ -149,17 +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( tibt, TIBT, "Tibetan" )
 
 #endif /* AF_CONFIG_OPTION_INDIC */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 78e3fd7..ef62043 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter types (specification only).                              */
 /*                                                                         */
-/*  Copyright 2003-2015 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;
@@ -209,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 );
 
@@ -247,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,
@@ -262,7 +270,7 @@
 
   } AF_WritingSystem;
 
-#undef  __AFWRTSYS_H__
+#undef  AFWRTSYS_H_
 
 
   typedef struct  AF_WritingSystemClassRec_
@@ -273,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;
@@ -291,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. */
@@ -329,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;
 
@@ -469,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
 
@@ -483,6 +499,7 @@
           m_init,                                        \
           m_scale,                                       \
           m_done,                                        \
+          m_stdw,                                        \
           h_init,                                        \
           h_apply )                                      \
   FT_CALLBACK_TABLE_DEF                                  \
@@ -495,6 +512,7 @@
     m_init,                                              \
     m_scale,                                             \
     m_done,                                              \
+    m_stdw,                                              \
                                                          \
     h_init,                                              \
     h_apply                                              \
@@ -509,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,                       \
   };
 
 
@@ -562,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;                                  \
   }
 
 
@@ -583,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;        \
   }
 
 
@@ -625,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 59af4f0..ce1806c 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter warping algorithm (body).                                */
 /*                                                                         */
-/*  Copyright 2006-2015 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,       */
@@ -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 5a6208a..6d96f86 100644
--- a/src/autofit/afwarp.h
+++ b/src/autofit/afwarp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter warping algorithm (specification).                       */
 /*                                                                         */
-/*  Copyright 2006-2015 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) & ~TYPEOF( 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 4aa89d2..842f492 100644
--- a/src/autofit/afwrtsys.h
+++ b/src/autofit/afwrtsys.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter writing systems (specification only).                    */
 /*                                                                         */
-/*  Copyright 2013-2015 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 b6ed4a0..dda9aeb 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module (body).                                           */
 /*                                                                         */
-/*  Copyright 2003-2015 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 5636ca6..0000000
--- a/src/autofit/hbshim.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  hbshim.h                                                               */
-/*                                                                         */
-/*    HarfBuzz interface for accessing OpenType features (specification).  */
-/*                                                                         */
-/*  Copyright 2013-2015 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 9850ed9..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-2015 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 51ecf9e..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-2015 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 f12908f..9e2ab89 100644
--- a/src/base/ftadvanc.c
+++ b/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (body).                          */
 /*                                                                         */
-/*  Copyright 2008-2015 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 */
@@ -87,7 +89,7 @@
       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;
 
@@ -133,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 )
@@ -157,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 f22a181..b94c3eb 100644
--- a/src/base/ftapi.c
+++ b/src/base/ftapi.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType compatibility functions (body).                         */
 /*                                                                         */
-/*  Copyright 2002-2015 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 253dfb7..ab1af6f 100644
--- a/src/base/ftbase.c
+++ b/src/base/ftbase.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Single object library component (body only).                         */
 /*                                                                         */
-/*  Copyright 1996-2015 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 cb57f96..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-2015 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 10df98d..d3e45ff 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType bbox computation (body).                                    */
 /*                                                                         */
-/*  Copyright 1996-2015 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/ftbitmap.c b/src/base/ftbitmap.c
index a54572a..24fead3 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (body).                       */
 /*                                                                         */
-/*  Copyright 2004-2015 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,       */
@@ -351,7 +351,7 @@
     }
 
     /* for each row */
-    for ( y = 0; y < bitmap->rows ; y++ )
+    for ( y = 0; y < bitmap->rows; y++ )
     {
       /*
        * Horizontally:
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index dca0e1d..67549d0 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Arithmetic computations (body).                                      */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -86,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;
   }
 
 
@@ -96,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;
   }
 
 
@@ -106,8 +104,7 @@
   FT_EXPORT_DEF( FT_Fixed )
   FT_FloorFix( FT_Fixed  a )
   {
-    return a >= 0 ?   a & ~0xFFFFL
-                  : -((-a) & ~0xFFFFL );
+    return a & ~0xFFFFL;
   }
 
 #ifndef FT_MSB
@@ -236,26 +233,14 @@
   {
 #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_UInt64  a, b, c;
-    FT_Long    c_;
+    FT_Int64  ab = (FT_Int64)a_ * (FT_Int64)b_;
 
-
-    FT_MOVE_SIGN( a_, s );
-    FT_MOVE_SIGN( b_, s );
-
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-
-    c = ( a * b + 0x8000UL ) >> 16;
-
-    c_ = (FT_Long)c;
-
-    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 */
   }
@@ -437,9 +422,6 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    if ( a_ == 0 || b_ == c_ )
-      return a_;
-
     FT_MOVE_SIGN( a_, s );
     FT_MOVE_SIGN( b_, s );
     FT_MOVE_SIGN( c_, s );
@@ -488,9 +470,6 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    if ( a_ == 0 || b_ == c_ )
-      return a_;
-
     FT_MOVE_SIGN( a_, s );
     FT_MOVE_SIGN( b_, s );
     FT_MOVE_SIGN( c_, s );
@@ -546,9 +525,6 @@
     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
@@ -599,9 +575,6 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    if ( a_ == 0 || b_ == 0x10000L )
-      return a_;
-
     FT_MOVE_SIGN( a_, s );
     FT_MOVE_SIGN( b_, s );
 
@@ -785,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 */
@@ -832,52 +901,34 @@
                          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;
 
 
@@ -895,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
   }
 
 
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 6f20313..38d1a80 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Memory debugger (body).                                              */
 /*                                                                         */
-/*  Copyright 2001-2015 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,       */
@@ -367,7 +367,8 @@
         {
           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 );
 
@@ -462,7 +463,7 @@
               (FT_UInt32)( 5 * _ft_debug_lineno );
     pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
 
-    for ( ;; )
+    for (;;)
     {
       node = *pnode;
       if ( node == NULL )
@@ -841,7 +842,7 @@
         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 )
@@ -854,7 +855,7 @@
         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 )
@@ -867,7 +868,7 @@
         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 )
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index 2cdb7c2..40925d1 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2015 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/ftfntfmt.c b/src/base/ftfntfmt.c
index 98e7431..c6eb319 100644
--- a/src/base/ftfntfmt.c
+++ b/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility file for font formats (body).                       */
 /*                                                                         */
-/*  Copyright 2002-2015 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/ftfstype.c b/src/base/ftfstype.c
index cd3458f..ae56c8f 100644
--- a/src/base/ftfstype.c
+++ b/src/base/ftfstype.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility file to access FSType data (body).                  */
 /*                                                                         */
-/*  Copyright 2008-2015 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,       */
diff --git a/src/base/ftgasp.c b/src/base/ftgasp.c
index bbd257c..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-2015 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 7e28638..c4f0ff7 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph loader (body).                                    */
 /*                                                                         */
-/*  Copyright 2002-2015 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/ftglyph.c b/src/base/ftglyph.c
index cb7fc37..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-2015 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,       */
@@ -125,10 +125,10 @@
     FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
 
 
-    cbox->xMin = glyph->left << 6;
-    cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width << 6 );
-    cbox->yMax = glyph->top << 6;
-    cbox->yMin = cbox->yMax - (FT_Pos)( 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 );
   }
 
 
@@ -403,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 );
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 cc95e6a..02ef938 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType initialization layer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2015 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,   */
@@ -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 )
@@ -256,6 +365,8 @@
     else
       FT_Add_Default_Modules( *alibrary );
 
+    ft_set_default_properties( *alibrary );
+
     return error;
   }
 
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index ff6f7e9..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-2015 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,       */
@@ -296,6 +296,8 @@
       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;
   }
@@ -305,12 +307,10 @@
   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 )
@@ -324,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:
@@ -354,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 7c012aa..6b759ca 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Multiple Master font support (body).                                 */
 /*                                                                         */
-/*  Copyright 1996-2015 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/ftobjs.c b/src/base/ftobjs.c
index 9c3332c..9006b59 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (body).                            */
 /*                                                                         */
-/*  Copyright 1996-2015 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 )
@@ -675,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 &&
@@ -1375,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 );
@@ -1407,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.                                                     */
 
@@ -1472,6 +1483,7 @@
       if ( face_index >= 0 && pstable_index == face_index )
         return FT_Err_Ok;
     }
+
     return FT_THROW( Table_Missing );
   }
 
@@ -1495,6 +1507,10 @@
     FT_UNUSED( params );
 
 
+    /* ignore GX stuff */
+    if ( face_index > 0 )
+      face_index &= 0xFFFFL;
+
     pos = FT_STREAM_POS();
 
     error = ft_lookup_PS_in_sfnt_stream( stream,
@@ -1505,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 ) )
@@ -1513,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,
@@ -1582,12 +1615,14 @@
       /* FT2 allocator takes signed long buffer length,
        * too large value causing overflow should be checked
        */
-      FT_TRACE4(( "                 POST fragment #%d: length=0x%08x\n",
-                  i, temp));
-      if ( 0x7FFFFFFFUL < temp || pfb_len + temp + 6 < pfb_len )
+      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(( "             too long fragment length makes"
-                    " pfb_len confused: temp=0x%08x\n", temp ));
+        FT_TRACE2(( "             MacOS resource length cannot exceed"
+                    " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
         error = FT_THROW( Invalid_Offset );
         goto Exit;
       }
@@ -1660,7 +1695,7 @@
       else
       {
         FT_TRACE3(( "    Write POST fragment #%d header (4-byte) to buffer"
-                    " 0x%p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
+                    " %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 );
@@ -1672,7 +1707,7 @@
           break;
 
         FT_TRACE3(( "    Write POST fragment #%d header (6-byte) to buffer"
-                    " 0x%p + 0x%08x\n", i, pfb_data, pfb_pos ));
+                    " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
         if ( pfb_pos + 6 > pfb_len + 2 )
           goto Exit2;
         pfb_data[pfb_pos++] = 0x80;
@@ -1692,7 +1727,7 @@
         goto Exit2;
 
       FT_TRACE3(( "    Load POST fragment #%d (%d byte) to buffer"
-                  " 0x%p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
+                  " %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;
@@ -1737,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,
@@ -1756,8 +1791,8 @@
     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 );
 
@@ -1770,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,
@@ -1780,14 +1817,17 @@
       goto Exit;
 
     /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
-    if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
+    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 )
+    if ( error ) {
+      FT_FREE( sfnt_data );
       goto Exit;
+    }
 
     is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
     error = open_face_from_buffer( library,
@@ -1889,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 ) |
@@ -2032,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 );
 
@@ -2154,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,
@@ -2268,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;
+        }
       }
     }
 
@@ -2572,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;
@@ -2591,6 +2653,8 @@
       }
     }
 
+    FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ));
+
     return FT_THROW( Invalid_Pixel_Size );
   }
 
@@ -3068,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
           }
         }
       }
@@ -3350,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;
   }
 
@@ -3370,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 );
     }
 
@@ -4116,39 +4203,51 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_bitmap
 
-    /* we convert to a single bitmap format for computing the checksum */
-    if ( !error )
+    /*
+     * 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_Init( &bitmap );
-
-      /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
-      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;
-        unsigned int   rows  = bitmap.rows;
-        unsigned int   pitch = (unsigned int)bitmap.pitch;
+        FT_Bitmap  bitmap;
+        FT_Error   err;
 
 
-        MD5_Init( &ctx );
-        MD5_Update( &ctx, bitmap.buffer, rows * pitch );
-        MD5_Final( md5, &ctx );
+        FT_Bitmap_Init( &bitmap );
 
-        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" ));
+        /* 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
@@ -4242,7 +4341,7 @@
   {
     FT_Error   error;
     FT_Memory  memory;
-    FT_Module  module;
+    FT_Module  module = NULL;
     FT_UInt    nn;
 
 
@@ -4483,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;
@@ -4553,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 );
   }
 
 
@@ -4570,7 +4675,8 @@
                            module_name,
                            property_name,
                            (void*)value,
-                           TRUE );
+                           TRUE,
+                           FALSE );
   }
 
 
@@ -4586,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
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index d821c49..fc28225 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType outline management (body).                                  */
 /*                                                                         */
-/*  Copyright 1996-2015 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;
@@ -414,11 +415,14 @@
     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;
@@ -907,8 +911,7 @@
                          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;
 
 
@@ -934,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( 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 );
+          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;
@@ -1066,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 bf2b085..4861be1 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -3,9 +3,9 @@
 /*  ftpatent.c                                                             */
 /*                                                                         */
 /*    FreeType API for checking patented TrueType bytecode instructions    */
-/*    (body).                                                              */
+/*    (body).  Obsolete, retained for backwards compatibility.             */
 /*                                                                         */
-/*  Copyright 2007-2015 by                                                 */
+/*  Copyright 2007-2016 by                                                 */
 /*  David Turner.                                                          */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,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;
   }
 
 
@@ -266,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 6c4b1cd..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-2015 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 82d54f8..4660c97 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (body).                             */
 /*                                                                         */
-/*  Copyright 2004-2015 by                                                 */
+/*  Copyright 2004-2016 by                                                 */
 /*  Masatake YAMATO and Redhat K.K.                                        */
 /*                                                                         */
 /*  FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are     */
@@ -71,24 +71,35 @@
     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 );
 
+    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;
@@ -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,
diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c
index 80304e5..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-2015 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 b68f3f8..bb512a7 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    I/O stream support (body).                                           */
 /*                                                                         */
-/*  Copyright 2000-2015 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,       */
@@ -778,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 842ee30..4f3c493 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002-2015 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 */
 
@@ -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 */
     {
@@ -2285,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 )
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index cd68533..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-2015 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,       */
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 1938fd8..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-2015 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/fttrigon.c b/src/base/fttrigon.c
index 5b24304..7b582c8 100644
--- a/src/base/fttrigon.c
+++ b/src/base/fttrigon.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (body).                             */
 /*                                                                         */
-/*  Copyright 2001-2015 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,       */
@@ -71,7 +71,8 @@
 
     /* 0x40000000 comes from regression analysis between true */
     /* and CORDIC hypotenuse, so it minimizes the error       */
-    val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
+    val = (FT_Fixed)(
+            ( (FT_UInt64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
 
     return s < 0 ? -val : val;
   }
diff --git a/src/base/fttype1.c b/src/base/fttype1.c
index c549382..5c0fce8 100644
--- a/src/base/fttype1.c
+++ b/src/base/fttype1.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility file for PS names support (body).                   */
 /*                                                                         */
-/*  Copyright 2002-2015 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/ftutil.c b/src/base/ftutil.c
index f5b72db..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-2015 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/ftwinfnt.c b/src/base/ftwinfnt.c
index 76a19af..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-2015 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,       */
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/cff/cf2arrst.c b/src/cff/cf2arrst.c
index 528b1fa..89f3e9f 100644
--- a/src/cff/cf2arrst.c
+++ b/src/cff/cf2arrst.c
@@ -104,7 +104,7 @@
       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 d6d9faf..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
@@ -89,7 +89,7 @@
 FT_END_HEADER
 
 
-#endif /*  __CF2FIXED_H__ */
+#endif /* CF2FIXED_H_ */
 
 
 /* END */
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
index 86cf02f..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"
@@ -54,6 +54,7 @@
                                    /* (Hiragino Kaku Gothic ProN W3;      */
                                    /* 8.2d6e1; 2014-12-19) that exceed    */
                                    /* this limit                          */
+#define CF2_STORAGE_SIZE        32
 
 
   /* typedef is in `cf2glue.h' */
@@ -115,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 d2544a2..55f3206 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -544,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 += (CF2_UInt)decoder->globals_bias;
+    idx = (CF2_UInt)( subrNum + decoder->globals_bias );
     if ( idx >= decoder->num_globals )
       return TRUE;     /* error */
 
@@ -628,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 += (CF2_UInt)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 3073df3..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,7 +99,7 @@
 
   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,
@@ -110,7 +110,7 @@
                          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 0e27000..bbbe8e3 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -587,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;
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 537e060..10e7b4b 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -184,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 */
@@ -293,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 );
 
@@ -446,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;
 
@@ -466,6 +469,8 @@
     CF2_GlyphPathRec  glyphPath;
 
 
+    FT_ZERO( &storage );
+
     /* initialize the remaining objects */
     cf2_arrstack_init( &subrStack,
                        memory,
@@ -608,7 +613,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         break;
 
@@ -632,7 +637,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         break;
 
@@ -646,7 +651,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curY += cf2_stack_popFixed( opStack );
 
@@ -746,7 +751,7 @@
       case cf2_cmdCALLGSUBR:
       case cf2_cmdCALLSUBR:
         {
-          CF2_UInt  subrIndex;
+          CF2_Int  subrNum;
 
 
           FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
@@ -766,17 +771,17 @@
                            (size_t)charstringIndex + 1 );
 
           /* set up the new CFF region and pointer */
-          subrIndex = (CF2_UInt)cf2_stack_popInt( opStack );
+          subrNum = cf2_stack_popInt( opStack );
 
           switch ( op1 )
           {
           case cf2_cmdCALLGSUBR:
             FT_TRACE4(( " (idx %d, entering level %d)\n",
-                        subrIndex + (CF2_UInt)decoder->globals_bias,
+                        subrNum + decoder->globals_bias,
                         charstringIndex + 1 ));
 
             if ( cf2_initGlobalRegionBuffer( decoder,
-                                             subrIndex,
+                                             subrNum,
                                              charstring ) )
             {
               lastError = FT_THROW( Invalid_Glyph_Format );
@@ -787,11 +792,11 @@
           default:
             /* cf2_cmdCALLSUBR */
             FT_TRACE4(( " (idx %d, entering level %d)\n",
-                        subrIndex + (CF2_UInt)decoder->locals_bias,
+                        subrNum + decoder->locals_bias,
                         charstringIndex + 1 ));
 
             if ( cf2_initLocalRegionBuffer( decoder,
-                                            subrIndex,
+                                            subrNum,
                                             charstring ) )
             {
               lastError = FT_THROW( Invalid_Glyph_Format );
@@ -833,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" ));
@@ -918,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:
             {
@@ -1085,7 +1280,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         /* close path if still open */
         cf2_glyphpath_closeOpenPath( &glyphPath );
@@ -1117,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,
@@ -1172,7 +1367,7 @@
                      0 );
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         if ( op1 == cf2_cmdHINTMASK )
         {
@@ -1231,7 +1426,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curY += cf2_stack_popFixed( opStack );
         curX += cf2_stack_popFixed( opStack );
@@ -1250,7 +1445,7 @@
         haveWidth = TRUE;
 
         if ( font->decoder->width_only )
-            goto exit;
+          goto exit;
 
         curX += cf2_stack_popFixed( opStack );
 
@@ -1305,7 +1500,7 @@
           /* 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 & ~2;
+          count  = count1 & ~2U;
           index += count1 - count;
 
           FT_TRACE4(( " vvcurveto\n" ));
@@ -1350,7 +1545,7 @@
           /* 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 & ~2;
+          count  = count1 & ~2U;
           index += count1 - count;
 
           FT_TRACE4(( " hhcurveto\n" ));
@@ -1399,7 +1594,7 @@
           /* 8n+4, or 8n+5, we enforce it by clearing the     */
           /* second bit                                       */
           /* (and sorting the stack indexing to suit)         */
-          count  = count1 & ~2;
+          count  = count1 & ~2U;
           index += count1 - count;
 
           FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
@@ -1463,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 ));
 
@@ -1527,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 bb2cfb5..86ca1be 100644
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType OpenType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2015 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 e7538e9..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-2015 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/cff/cffcmap.h b/src/cff/cffcmap.h
index 6eaed63..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-2015 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 a718b7a..67bf09d 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -358,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 */
   )
 
 
@@ -421,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   */
   )
 
 
@@ -444,7 +446,7 @@
     /* following the OpenType specification 1.7, we return the name stored */
     /* in the `name' table for a CFF wrapped into an SFNT container        */
 
-    if ( sfnt )
+    if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
     {
       FT_Library             library     = FT_FACE_LIBRARY( face );
       FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
@@ -464,7 +466,7 @@
 
   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 */
   )
 
 
@@ -511,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 */
   )
 
 
@@ -641,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 */
   )
 
 
@@ -654,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              ||
@@ -693,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;
     }
@@ -776,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 */
 
 
   /*************************************************************************/
@@ -865,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",
@@ -876,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 9527f5e..d7b0598 100644
--- a/src/cff/cffdrivr.h
+++ b/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level OpenType driver interface (specification).                */
 /*                                                                         */
-/*  Copyright 1996-2015 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 543bdb0..e7fc6eb 100644
--- a/src/cff/cfferrs.h
+++ b/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF error codes (specification only).                                */
 /*                                                                         */
-/*  Copyright 2001-2015 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 43054f8..4f375a6 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -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,
@@ -826,7 +826,7 @@
       /* 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 );
@@ -856,7 +856,7 @@
       /* 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;
 
@@ -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:
@@ -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. */
@@ -2082,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;
             }
@@ -2199,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;
           }
@@ -2221,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 */
@@ -2358,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;
@@ -2489,7 +2610,6 @@
           break;
 
         default:
-        Unimplemented:
           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
           if ( ip[-1] == 12 )
@@ -2513,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 );
@@ -2586,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 );
       }
@@ -2816,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;
 
@@ -2837,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
       {
@@ -2949,7 +3077,6 @@
       {
         FT_BBox            cbox;
         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
-        FT_Vector          advance;
         FT_Bool            has_vertical_info;
 
 
@@ -3014,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 )
         {
@@ -3064,9 +3192,7 @@
         metrics->width  = cbox.xMax - cbox.xMin;
         metrics->height = cbox.yMax - cbox.yMin;
 
-        if ( !face->horizontal.number_Of_HMetrics )
-          metrics->horiBearingX = cbox.xMin;
-
+        metrics->horiBearingX = cbox.xMin;
         metrics->horiBearingY = cbox.yMax;
 
         if ( has_vertical_info )
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 5f2655f..b875fbe 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2015 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>
@@ -227,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 )
@@ -239,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 fcb7348..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-2015 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,       */
@@ -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 = (FT_Long)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;
     }
@@ -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 = (FT_UInt)face_index;
+      subfont_index = (FT_UInt)( face_index & 0xFFFF );
 
-      if ( subfont_index >= 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 459e7b0..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-2015 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 4a1ef11..0f07696 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -583,10 +583,18 @@
       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; */
@@ -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,9 +683,12 @@
         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_ULong)FT_DivFix( (FT_Long)*upm, temp );
@@ -711,7 +756,10 @@
         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 )
         {
@@ -765,8 +813,9 @@
           (FT_Short)( dict->underline_thickness >> 16 );
 
         /* retrieve font family & style name */
-        cffface->family_name = cff_index_get_name( cff,
-                                                   (FT_UInt)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,
@@ -1046,7 +1095,7 @@
     driver->hinting_engine = FT_CFF_HINTING_ADOBE;
 #endif
 
-    driver->no_stem_darkening = FALSE;
+    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;
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index 3cc9531..9dc7753 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2015 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 063b351..a4f986b 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (body)                                       */
 /*                                                                         */
-/*  Copyright 1996-2015 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;
   }
 
 
@@ -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 = (FT_ULong)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,
@@ -649,6 +701,56 @@
   }
 
 
+  /* 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;
+  }
+
+
   static FT_Error
   cff_parse_cid_ros( CFF_Parser  parser )
   {
@@ -972,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 )
@@ -1001,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 8ad02ea..a95970e 100644
--- a/src/cff/cffparse.h
+++ b/src/cff/cffparse.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (specification)                              */
 /*                                                                         */
-/*  Copyright 1996-2015 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 d40dec5..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-2015 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 a29620e..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-2015 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 5b32076..22637c7 100644
--- a/src/cff/cfftoken.h
+++ b/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token definitions (specification only).                          */
 /*                                                                         */
-/*  Copyright 1996-2015 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 de8a5ee..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-2015 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 879eb88..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-2015 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_
@@ -59,7 +59,7 @@
  /* original ZLib.                                                   */
 
 #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"
@@ -377,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
     {
@@ -386,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 );
     }
@@ -433,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;
       }
     }
@@ -557,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 );
   }
 
 
@@ -584,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;
 
@@ -681,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;
 
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/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index bfdb3ed..8f131be 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (body).                                 */
 /*                                                                         */
-/*  Copyright 2001-2015 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        */
@@ -779,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.
            */
@@ -802,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.
              */
@@ -916,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
 
diff --git a/src/pshinter/pshalgo.h b/src/pshinter/pshalgo.h
index 8373e5e..f1bda65 100644
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (specification).                        */
 /*                                                                         */
-/*  Copyright 2001-2015 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"
@@ -235,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 6723b71..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-2015 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        */
@@ -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 )
@@ -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
             {
diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h
index c376df7..45c957b 100644
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinter global hinting management.                         */
 /*                                                                         */
-/*  Copyright 2001-2015 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
@@ -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 9e65fe2..614e0bb 100644
--- a/src/pshinter/pshinter.c
+++ b/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript Hinting module                                   */
 /*                                                                         */
-/*  Copyright 2001-2015 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 961b468..fa4ad1f 100644
--- a/src/pshinter/pshmod.c
+++ b/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hinter module implementation (body).             */
 /*                                                                         */
-/*  Copyright 2001-2015 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 a58d856..39112a9 100644
--- a/src/pshinter/pshmod.h
+++ b/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinter module interface (specification).                  */
 /*                                                                         */
-/*  Copyright 2001-2015 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 ce790a8..7a94588 100644
--- a/src/pshinter/pshnterr.h
+++ b/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PS Hinter error codes (specification only).                          */
 /*                                                                         */
-/*  Copyright 2003-2015 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 afd8fb9..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-2015 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 62de457..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-2015 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 f8895fc..d7cc4a0 100644
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hints recorder (body).                           */
 /*                                                                         */
-/*  Copyright 2001-2015 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/pshrec.h b/src/pshinter/pshrec.h
index 2b1ad94..97e6f0e 100644
--- a/src/pshinter/pshrec.h
+++ b/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Postscript (Type1/Type2) hints recorder (specification).             */
 /*                                                                         */
-/*  Copyright 2001-2015 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>
@@ -166,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 0f04c2f..345402d 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PSNames module implementation (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -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 */
 
diff --git a/src/psnames/psmodule.h b/src/psnames/psmodule.h
index f85f322..ee3c6cb 100644
--- a/src/psnames/psmodule.h
+++ b/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level PSNames module interface (specification).                 */
 /*                                                                         */
-/*  Copyright 1996-2015 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 09cc247..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-2015 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 a438596..e7b2c0b 100644
--- a/src/psnames/psnames.c
+++ b/src/psnames/psnames.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PSNames module component (body only).                       */
 /*                                                                         */
-/*  Copyright 1996-2015 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 1394f97..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-2015 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 88ccda3..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-2015 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 3f31c31..eb827fa 100644
--- a/src/psnames/pstables.h
+++ b/src/psnames/pstables.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript glyph names.                                              */
 /*                                                                         */
-/*  Copyright 2005-2015 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 19be4ca..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-2015 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 eeab143..0fa2f26 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2015 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,7 @@
   /*                                                                       */
   /*************************************************************************/
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
   /* The size in bytes of the render pool used by the scan-line converter  */
   /* to do all of its work.                                                */
@@ -60,7 +60,7 @@
 #include "ftmisc.h"
 #include "ftimage.h"
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 #include <ft2build.h>
 #include "ftraster.h"
@@ -68,7 +68,7 @@
 
 #include "rastpic.h"
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
   /*************************************************************************/
@@ -173,14 +173,12 @@
 #define FT_COMPONENT  trace_raster
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
   /* Auxiliary macros for token concatenation. */
 #define FT_ERR_XCAT( x, y )  x ## y
 #define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
 
-#define FT_MAX( a, b )  ( (a) > (b) ? (a) : (b) )
-
   /* This macro is used to indicate that a function parameter is unused. */
   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
@@ -226,7 +224,7 @@
             raster_done_                                            \
          };
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
 #include FT_INTERNAL_OBJECTS_H
@@ -242,7 +240,7 @@
 #define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
 
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
 #ifndef FT_MEM_SET
@@ -450,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 )   ( ( (Long)(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.                                                 */
@@ -799,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 )
     {
@@ -848,7 +853,7 @@
 
     if ( n > 1 && p )
     {
-      while ( n > 0 )
+      do
       {
         Int  bottom, top;
 
@@ -876,8 +881,7 @@
           return FAILURE;
 
         p = p->link;
-        n--;
-      }
+      } while ( --n );
     }
     else
       ras.fProfile = NULL;
@@ -1248,7 +1252,7 @@
 
     start_arc = arc;
 
-    while ( arc >= start_arc && e <= e2 )
+    do
     {
       ras.joint = FALSE;
 
@@ -1281,7 +1285,7 @@
         }
         arc -= degree;
       }
-    }
+    } while ( arc >= start_arc && e <= e2 );
 
   Fin:
     ras.top  = top;
@@ -2114,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;
     }
@@ -3041,7 +3045,7 @@
   /****                         a static object.                  *****/
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
 
   static int
@@ -3068,7 +3072,7 @@
   }
 
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
   static int
@@ -3102,13 +3106,13 @@
   }
 
 
-#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 )
   {
     FT_UNUSED( raster );
     FT_UNUSED( pool_base );
@@ -3117,20 +3121,20 @@
 
 
   static int
-  ft_black_set_mode( black_PRaster  raster,
-                     ULong          mode,
-                     const char*    palette )
+  ft_black_set_mode( FT_Raster  raster,
+                     ULong      mode,
+                     void*      args )
   {
     FT_UNUSED( raster );
     FT_UNUSED( mode );
-    FT_UNUSED( palette );
+    FT_UNUSED( args );
 
     return 0;
   }
 
 
   static int
-  ft_black_render( black_PRaster            raster,
+  ft_black_render( FT_Raster                raster,
                    const FT_Raster_Params*  params )
   {
     const FT_Outline*  outline    = (const FT_Outline*)params->source;
@@ -3138,7 +3142,7 @@
 
     black_TWorker  worker[1];
 
-    Long  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( Long )];
+    Long  buffer[FT_MAX_BLACK_POOL];
 
 
     if ( !raster )
@@ -3175,6 +3179,20 @@
     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;
 
diff --git a/src/raster/ftraster.h b/src/raster/ftraster.h
index a270d48..65cd5f9 100644
--- a/src/raster/ftraster.h
+++ b/src/raster/ftraster.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (specification).                       */
 /*                                                                         */
-/*  Copyright 1996-2015 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 f314392..494f112 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer interface (body).                      */
 /*                                                                         */
-/*  Copyright 1996-2015 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/ftrend1.h b/src/raster/ftrend1.h
index c367260..a431f18 100644
--- a/src/raster/ftrend1.h
+++ b/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer interface (specification).             */
 /*                                                                         */
-/*  Copyright 1996-2015 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 21bb16d..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-2015 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 e7f00bc..44da7fc 100644
--- a/src/raster/rasterrs.h
+++ b/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    monochrome renderer error codes (specification only).                */
 /*                                                                         */
-/*  Copyright 2001-2015 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 fe58c99..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-2015 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 a875884..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-2015 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 ea60452..2815759 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PNG Bitmap glyph support.                                            */
 /*                                                                         */
-/*  Copyright 2013-2015 by                                                 */
+/*  Copyright 2013-2016 by                                                 */
 /*  Google, Inc.                                                           */
 /*  Written by Stuart Gill and Behdad Esfahbod.                            */
 /*                                                                         */
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
index 4cc5c2b..ff05871 100644
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PNG Bitmap glyph support.                                            */
 /*                                                                         */
-/*  Copyright 2013-2015 by                                                 */
+/*  Copyright 2013-2016 by                                                 */
 /*  Google, Inc.                                                           */
 /*  Written by Stuart Gill and Behdad Esfahbod.                            */
 /*                                                                         */
@@ -17,8 +17,8 @@
 /***************************************************************************/
 
 
-#ifndef __PNGSHIM_H__
-#define __PNGSHIM_H__
+#ifndef PNGSHIM_H_
+#define PNGSHIM_H_
 
 
 #include <ft2build.h>
@@ -44,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 0948ad4..2233269 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (body).                             */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -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 */
@@ -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 */
@@ -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 944119c..2694488 100644
--- a/src/sfnt/sfdriver.h
+++ b/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2015 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 e3bef3f..c2f9fdf 100644
--- a/src/sfnt/sferrors.h
+++ b/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT error codes (specification only).                               */
 /*                                                                         */
-/*  Copyright 2001-2015 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 0b8b5f4..952d6d4 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Single object library component.                                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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 2aaf4bc..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-2015 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 563d634..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-2015 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 40c27fa..ceeae20 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (base).                                       */
 /*                                                                         */
-/*  Copyright 1996-2015 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 )
@@ -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;
       }
@@ -573,6 +561,7 @@
            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;
       }
@@ -598,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;
       }
@@ -614,6 +605,7 @@
       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;
       }
@@ -625,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++ )
@@ -669,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;
         }
@@ -839,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 */
@@ -878,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;
   }
@@ -946,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 )
   {
@@ -962,7 +1044,7 @@
 
     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 
-    FT_UNUSED( face_index );
+    FT_UNUSED( face_instance_index );
 
 
     /* Check parameters */
@@ -1284,7 +1366,7 @@
           flags |= FT_STYLE_FLAG_ITALIC;
       }
 
-      root->style_flags = flags;
+      root->style_flags |= flags;
 
       /*********************************************************************/
       /*                                                                   */
@@ -1329,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;
@@ -1341,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 )
           {
@@ -1348,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;
+          }
         }
       }
 
@@ -1566,6 +1670,7 @@
 
     /* 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 );
diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h
index 77c7d92..60b5698 100644
--- a/src/sfnt/sfobjs.h
+++ b/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (specification).                              */
 /*                                                                         */
-/*  Copyright 1996-2015 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 098b781..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-2015 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 fe4ba48..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-2015 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 815ee7c..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-2015 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;
 
@@ -436,6 +443,7 @@
       }
       result = sub;
     }
+
   Exit:
     return result;
   }
@@ -475,6 +483,7 @@
           result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
       }
     }
+
     return result;
   }
 
@@ -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)( (FT_Int)gindex + delta ) & 0xFFFFU;
-              if ( gindex != 0 )
+              if ( gindex )
               {
                 cmap->cur_charcode = charcode;
                 cmap->cur_gindex   = gindex;
@@ -803,7 +819,26 @@
             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;
@@ -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 ) )
           {
@@ -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)( (FT_Int)gindex + delta ) & 0xFFFFU;
-          }
-          else
-            gindex = (FT_UInt)( (FT_Int)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,13 +1373,40 @@
         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 )
+          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 );
+          }
+        }
+
         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'.   *****/
   /*****                                                               *****/
@@ -1770,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;
       }
     }
@@ -1782,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;
@@ -1791,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-- )
@@ -1802,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;
   }
@@ -1930,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;
   }
 
@@ -1947,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 );
@@ -1955,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++ )
@@ -1966,6 +2117,10 @@
       gindex = TT_NEXT_USHORT( p );
       if ( gindex != 0 )
         break;
+
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
     }
 
@@ -2134,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;
@@ -2155,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;
       }
     }
 
@@ -2196,7 +2372,12 @@
     end = 0xFFFFFFFFUL;
 
     if ( next )
+    {
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
+    }
 
     min = 0;
     max = num_groups;
@@ -2217,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 )
       {
@@ -2243,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 );
@@ -2253,8 +2441,7 @@
       else
         cmap12->cur_gindex = gindex;
 
-      if ( gindex )
-        *pchar_code = cmap12->cur_charcode;
+      *pchar_code = cmap12->cur_charcode;
     }
 
     return gindex;
@@ -2274,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;
@@ -2298,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;
   }
 
 
@@ -2458,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;
@@ -2483,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;
 
@@ -2520,7 +2701,12 @@
     end = 0xFFFFFFFFUL;
 
     if ( next )
+    {
+      if ( char_code >= 0xFFFFFFFFUL )
+        return 0;
+
       char_code++;
+    }
 
     min = 0;
     max = num_groups;
@@ -2548,6 +2734,7 @@
 
     if ( next )
     {
+      FT_Face    face   = cmap->cmap.charmap.face;
       TT_CMap13  cmap13 = (TT_CMap13)cmap;
 
 
@@ -2565,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 );
@@ -2575,8 +2765,7 @@
       else
         cmap13->cur_gindex = gindex;
 
-      if ( gindex )
-        *pchar_code = cmap13->cur_charcode;
+      *pchar_code = cmap13->cur_charcode;
     }
 
     return gindex;
@@ -2599,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;
@@ -2836,12 +3021,17 @@
         /* 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 + 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;
@@ -2865,13 +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;
 
 
-          /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */
-          if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 )
+          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 )
@@ -2962,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;
@@ -3316,7 +3511,7 @@
       ni   = 1;
       i    = 0;
 
-      for ( ;; )
+      for (;;)
       {
         if ( nuni > duni + dcnt )
         {
diff --git a/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h
index b7ea8ee..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-2015 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 4a48940..7c732fb 100644
--- a/src/sfnt/ttcmapc.h
+++ b/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TT CMAP classes definitions (specification only).                    */
 /*                                                                         */
-/*  Copyright 2009-2015 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 4fccc53..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-2015 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/ttkern.h b/src/sfnt/ttkern.h
index 89cb24f..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-2015 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 ad2975d..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-2015 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;
@@ -209,7 +211,10 @@
       /* we ignore invalid tables */
 
       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     */
@@ -273,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;
     }
@@ -333,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[] =
     {
@@ -375,85 +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;
+
+
+      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 )
+      if ( entry.Offset > stream->size )
         continue;
-      else if ( entry->Length > stream->size - entry->Offset )
+      else if ( entry.Length > stream->size - entry.Offset )
       {
-        if ( entry->Tag == TTAG_hmtx ||
-             entry->Tag == TTAG_vmtx )
+        if ( entry.Tag == TTAG_hmtx ||
+             entry.Tag == TTAG_vmtx )
         {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_ULong  old_length = entry->Length;
+          FT_ULong  old_length = entry.Length;
 #endif
 
 
           /* make metrics table length a multiple of 4 */
-          entry->Length = ( stream->size - entry->Offset ) & ~3U;
+          entry.Length = ( stream->size - entry.Offset ) & ~3U;
 
           FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx"
-                      " (sanitized; original length %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,
+                      " (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 ));
-          entry++;
         }
         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" ));
@@ -742,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 ));
@@ -1160,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 a6d91c5..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-2015 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 58309aa..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-2015 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,       */
diff --git a/src/sfnt/ttmtx.h b/src/sfnt/ttmtx.h
index 096ee06..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-2015 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>
@@ -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 8d29d1e..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-2015 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/ttpost.h b/src/sfnt/ttpost.h
index e3eca02..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-2015 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 143f276..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-2015 by                                                 */
+/*  Copyright 2005-2016 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  Copyright 2013 by Google, Inc.                                         */
@@ -104,7 +104,8 @@
         version     = FT_NEXT_LONG( p );
         num_strikes = FT_NEXT_ULONG( p );
 
-        if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL )
+        if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL &&
+             ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL )
         {
           error = FT_THROW( Unknown_File_Format );
           goto Exit;
@@ -196,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:
@@ -238,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 )
     {
@@ -247,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;
@@ -254,26 +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_, upem_; /* to reduce casts */
+        FT_Pos          ppem_; /* to reduce casts */
 
         FT_Error  error;
         FT_Byte*  p;
@@ -307,14 +413,16 @@
         metrics->y_ppem = ppem;
 
         ppem_ = (FT_Pos)ppem;
-        upem_ = (FT_Pos)upem;
 
-        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_;
+        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;
       }
@@ -352,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;
@@ -373,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;
@@ -547,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
@@ -561,7 +670,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_Byte*    line;
@@ -569,6 +679,8 @@
     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;
@@ -700,7 +812,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_Byte*    line;
@@ -709,6 +822,8 @@
     FT_Bitmap*  bitmap;
     FT_UShort   rval;
 
+    FT_UNUSED( recurse_count );
+
 
     /* check that we can write the glyph into the bitmap */
     bitmap     = decoder->bitmap;
@@ -738,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 */
@@ -777,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;
@@ -824,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;
@@ -858,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;
     }
@@ -891,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 )
     {
@@ -937,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;
@@ -947,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;
@@ -1063,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:
@@ -1078,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;
@@ -1092,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 );
@@ -1256,7 +1393,8 @@
                                         image_start,
                                         image_end,
                                         x_pos,
-                                        y_pos );
+                                        y_pos,
+                                        recurse_count );
 
   Failure:
     return FT_THROW( Invalid_Table );
@@ -1289,6 +1427,8 @@
     FT_UNUSED( map );
 
 
+    strike_index = face->sbit_strike_map[strike_index];
+
     metrics->width  = 0;
     metrics->height = 0;
 
@@ -1419,6 +1559,7 @@
           error = tt_sbit_decoder_load_image( decoder,
                                               glyph_index,
                                               0,
+                                              0,
                                               0 );
           tt_sbit_decoder_done( decoder );
         }
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index d4e13ae..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-2015 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 77b58f2..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-2015 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,7 @@
 #define FT_COMPONENT  trace_smooth
 
 
-#ifdef _STANDALONE_
+#ifdef STANDALONE_
 
 
   /* The size in bytes of the render pool used by the scan-line converter  */
@@ -106,6 +106,7 @@
 #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) )
 
@@ -135,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
 
@@ -254,7 +257,7 @@
          };
 
 
-#else /* !_STANDALONE_ */
+#else /* !STANDALONE_ */
 
 
 #include <ft2build.h>
@@ -272,7 +275,7 @@
 #define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
 
 
-#endif /* !_STANDALONE_ */
+#endif /* !STANDALONE_ */
 
 
 #ifndef FT_MEM_SET
@@ -300,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 */
@@ -316,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
 
 
@@ -367,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                                                    */
@@ -376,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   */
@@ -428,9 +431,8 @@
     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;
@@ -440,33 +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;
-
-    void*       buffer;
-    long        buffer_size;
 
     PCell*     ycells;
-    TPos       ycount;
 
   } gray_TWorker, *gray_PWorker;
 
@@ -489,70 +473,31 @@
   } 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 */
 
 
   /*************************************************************************/
@@ -563,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;
@@ -632,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 int)ey >= (unsigned int)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.                               */
@@ -695,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 )
@@ -714,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;
@@ -727,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;
@@ -758,7 +671,7 @@
 
       mod -= (int)dx;
 
-      while ( ex1 != ex2 )
+      do
       {
         delta = lift;
         mod  += rem;
@@ -773,7 +686,7 @@
         y1        += delta;
         ex1       += incr;
         gray_set_cell( RAS_VAR_ ex1, ey );
-      }
+      } while ( ex1 != ex2 );
     }
 
     delta      = y2 - y1;
@@ -790,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 )
@@ -827,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 );
@@ -837,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 )
       {
@@ -862,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;
 
@@ -870,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;
@@ -882,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 )
@@ -952,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 );
   }
 
 
@@ -1055,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 );
@@ -1069,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 (;;)
     {
@@ -1100,64 +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 = dx_ = arc[3].x - arc[0].x;
-        dy = dy_ = arc[3].y - arc[0].y;
+      /* Avoid possible arithmetic overflow below by splitting. */
+      if ( L > 32767 )
+        goto Split;
 
-        L = FT_HYPOT( dx_, dy_ );
+      /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+      s_limit = L * (TPos)( ONE_PIXEL / 6 );
 
-        /* Avoid possible arithmetic overflow below by splitting. */
-        if ( L > 32767 )
-          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 );
 
-        /* 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 );
+      /* 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 ( s > s_limit )
-          goto Split;
+      if ( s > s_limit )
+        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 );
+      /* 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 );
 
-        /* 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 ( arc == bez_stack )
+        return;
 
-        /* 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;
     }
   }
 
@@ -1169,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;
   }
 
@@ -1216,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 += ( map->rows - 1 ) * (unsigned int)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    */
@@ -1301,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.     */
   /*                                                                       */
   /*************************************************************************/
@@ -1751,14 +1628,82 @@
     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;
+
+    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(
@@ -1788,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;
   }
 
@@ -1799,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 = (long)sizeof ( PCell ) * ras.ycount;
-          cell_mod   = cell_start % (long)sizeof ( TCell );
-          if ( cell_mod > 0 )
-            cell_start += (long)sizeof ( TCell ) - cell_mod;
-
-          cell_end  = ras.buffer_size;
-          cell_end -= cell_end % (long)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;
         }
@@ -1901,56 +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;
+    FT_BBox            cbox, clip;
 
+#ifndef FT_STATIC_RASTER
     gray_TWorker  worker[1];
-
-    TCell  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )];
-    long   buffer_size = sizeof ( buffer );
-    int    band_size   = (int)( buffer_size /
-                                (long)( sizeof ( TCell ) * 8 ) );
+#endif
 
 
     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 );
 
@@ -1965,9 +1880,19 @@
            outline->contours[outline->n_contours - 1] + 1 )
       return FT_THROW( Invalid_Outline );
 
-    /* if direct mode is not set, we must have a target bitmap */
-    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
+    ras.outline = *outline;
+
+    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 );
 
@@ -1977,51 +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 = (FT_Pos)target_map->width;
-      ras.clip_box.yMax = (FT_Pos)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_ buffer, 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      = band_size;
-    ras.num_gray_spans = 0;
-    ras.span_y         = 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,13 +2018,13 @@
     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 )
   {
     FT_UNUSED( raster );
     FT_UNUSED( pool_base );
diff --git a/src/smooth/ftgrays.h b/src/smooth/ftgrays.h
index 1b57603..21c2bad 100644
--- a/src/smooth/ftgrays.h
+++ b/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType smooth renderer declaration                                 */
 /*                                                                         */
-/*  Copyright 1996-2015 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 cc38aa1..a759b91 100644
--- a/src/smooth/ftsmerrs.h
+++ b/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    smooth renderer error codes (specification only).                    */
 /*                                                                         */
-/*  Copyright 2001-2015 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 3620550..7927676 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (body).                             */
 /*                                                                         */
-/*  Copyright 2000-2015 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,       */
diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h
index 765018c..c7c28c2 100644
--- a/src/smooth/ftsmooth.h
+++ b/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (specification).                    */
 /*                                                                         */
-/*  Copyright 1996-2015 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 8e6ed57..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-2015 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 99b9f0e..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-2015 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 4ca4344..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-2015 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 f929437..23e2ea0 100644
--- a/src/truetype/truetype.c
+++ b/src/truetype/truetype.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType TrueType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2015 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 08b30c9..b96a227 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -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 */
 
 
   /*************************************************************************/
@@ -194,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 */
@@ -228,6 +255,7 @@
     return FT_Err_Ok;
   }
 
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -263,7 +291,7 @@
     }
     else
     {
-      SFNT_Service      sfnt    = (SFNT_Service) ttface->sfnt;
+      SFNT_Service      sfnt    = (SFNT_Service)ttface->sfnt;
       FT_Size_Metrics*  metrics = &size->metrics;
 
 
@@ -291,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;
 
 
@@ -311,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;
@@ -417,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 */
 
@@ -441,9 +485,11 @@
 #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(
@@ -534,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 6cacd60..74392bb 100644
--- a/src/truetype/ttdriver.h
+++ b/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level TrueType driver interface (specification).                */
 /*                                                                         */
-/*  Copyright 1996-2015 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 ba32cf7..895989f 100644
--- a/src/truetype/tterrors.h
+++ b/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType error codes (specification only).                           */
 /*                                                                         */
-/*  Copyright 2001-2015 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 e1acd69..2d0b29f 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2015 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,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"
@@ -120,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
 
@@ -152,7 +153,7 @@
     loader->top_bearing  = top_bearing;
     loader->vadvance     = advance_height;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
          loader->exec                                             )
     {
@@ -164,7 +165,7 @@
       /* 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 )
     {
@@ -182,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;
@@ -250,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.           */
@@ -449,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 */
@@ -656,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;
@@ -682,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
 
@@ -753,8 +733,9 @@
   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
 
@@ -781,7 +762,7 @@
       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.     */
@@ -794,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
 
@@ -838,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 )
@@ -853,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;
   }
@@ -897,13 +886,13 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    if ( ((TT_Face)loader->face)->doblend )
+    if ( loader->face->doblend )
     {
       /* Deltas apply to the unscaled data. */
-      error = TT_Vary_Apply_Glyph_Deltas( (TT_Face)(loader->face),
-                                           loader->glyph_index,
-                                           outline,
-                                           (FT_UInt)n_points );
+      error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+                                          loader->glyph_index,
+                                          outline,
+                                          (FT_UInt)n_points );
       if ( error )
         return error;
     }
@@ -919,8 +908,8 @@
     }
 
     {
-#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;
@@ -938,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 )
       {
@@ -953,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 = FT_MulDiv( loader->size->metrics.x_scale,
                                (FT_Long)x_scale_factor, 1000 );
-          y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+          y_scale = loader->size->metrics.y_scale;
 
           /* compensate for any scaling by de/emboldening; */
           /* the amount was determined via experimentation */
@@ -969,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;
         }
@@ -1023,30 +1012,29 @@
                                   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 = (FT_UInt)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     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;
@@ -1101,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;
@@ -1135,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 );
@@ -1151,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;
   }
@@ -1215,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'; */
@@ -1349,49 +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_hinting_ = loader->exec                       \
-                                           ? loader->exec->subpixel_hinting \
-                                           : 0;                             \
-            FT_Bool  grayscale_        = loader->exec                       \
-                                           ? loader->exec->grayscale        \
-                                           : 0;                             \
-            FT_Bool  use_aw_2_         = (FT_Bool)( subpixel_hinting_ &&    \
-                                                    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;
+  }
 
 
   /*************************************************************************/
@@ -1412,7 +1420,7 @@
     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;
 
@@ -1423,13 +1431,17 @@
 #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
@@ -1445,8 +1457,8 @@
 
     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
     {
@@ -1544,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 );
@@ -1552,7 +1564,7 @@
 
 #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'  */
@@ -1579,10 +1591,10 @@
         outline.contours   = contours;
 
         /* this must be done before scaling */
-        error = TT_Vary_Apply_Glyph_Deltas( (TT_Face)(loader->face),
-                                             glyph_index,
-                                             &outline,
-                                             outline.n_points );
+        error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+                                            glyph_index,
+                                            &outline,
+                                            (FT_UInt)outline.n_points );
         if ( error )
           goto Exit;
 
@@ -1619,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 );
@@ -1655,10 +1667,48 @@
     /* 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;
+
+
+      /*
+       * 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;
@@ -1679,7 +1729,7 @@
 
       if ( face->doblend )
       {
-        FT_UInt      i, limit;
+        short        i, limit;
         FT_SubGlyph  subglyph;
 
         FT_Outline  outline;
@@ -1687,22 +1737,24 @@
         char*       tags     = NULL;
         short*      contours = NULL;
 
-        FT_Memory  memory = face->root.memory;
 
-
-        limit = gloader->current.num_subglyphs;
+        limit = (short)gloader->current.num_subglyphs;
 
         /* construct an outline structure for              */
         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
-        outline.n_points   = gloader->current.num_subglyphs + 4;
+        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 + gloader->base.num_subglyphs;
+        subglyph = gloader->current.subglyphs;
 
         for ( i = 0; i < limit; i++, subglyph++ )
         {
@@ -1748,18 +1800,18 @@
                          face,
                          glyph_index,
                          &outline,
-                         outline.n_points ) ) != 0 )
+                         (FT_UInt)outline.n_points ) ) != 0 )
           goto Exit1;
 
-        subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
+        subglyph = gloader->current.subglyphs;
 
         for ( i = 0; i < limit; i++, subglyph++ )
         {
-          /* XXX: overflow check for subglyph->{arg1,arg2}.         */
-          /*      Deltas must be within signed 16-bit,              */
-          /*      but the restriction of summed deltas is not clear */
-          subglyph->arg1 = (FT_Int16)points[i].x;
-          subglyph->arg2 = (FT_Int16)points[i].y;
+          if ( subglyph->flags & ARGS_ARE_XY_VALUES )
+          {
+            subglyph->arg1 = (FT_Int16)points[i].x;
+            subglyph->arg2 = (FT_Int16)points[i].y;
+          }
         }
 
         loader->pp1.x = points[i + 0].x;
@@ -1935,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;
@@ -1963,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;
 
@@ -1974,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 )
       {
@@ -1988,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;
       }
     }
 
@@ -2136,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;
 
@@ -2181,6 +2243,10 @@
 #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;
@@ -2194,11 +2260,13 @@
     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 );
-
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       FT_Bool  subpixel_hinting = FALSE;
 
 #if 0
@@ -2210,7 +2278,7 @@
       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;
 
@@ -2231,7 +2299,26 @@
       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 )
       {
@@ -2288,18 +2375,23 @@
       }
       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             );
 
       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 )
       {
@@ -2327,9 +2419,37 @@
       }
       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 )
@@ -2362,10 +2482,11 @@
       if ( exec->GS.instruct_control & 2 )
         exec->GS = tt_default_graphics_state;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#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 ( exec->GS.instruct_control & 4 )
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+           exec->GS.instruct_control & 4                            )
         exec->ignore_x_mode = 0;
 #endif
 
@@ -2414,15 +2535,28 @@
 
     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>                                                            */
@@ -2479,6 +2613,7 @@
           /* 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.vadvance;
 
@@ -2574,6 +2709,8 @@
       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 8e3255e..bfa29e4 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2015 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 2b12483..c0d013c 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader                                    */
 /*                                                                         */
-/*  Copyright 2004-2015 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,       */
@@ -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,6 +125,7 @@
   /*                                                                       */
   static FT_UShort*
   ft_var_readpackedpoints( FT_Stream  stream,
+                           FT_ULong   size,
                            FT_UInt   *point_cnt )
   {
     FT_UShort *points = NULL;
@@ -149,48 +152,55 @@
       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;
 
     *point_cnt = n;
 
-    i = 0;
+    first = 0;
+    i     = 0;
     while ( i < n )
     {
       runcnt = FT_GET_BYTE();
       if ( runcnt & GX_PT_POINTS_ARE_WORDS )
       {
         runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
-        first       = FT_GET_USHORT();
+        first      += FT_GET_USHORT();
         points[i++] = first;
 
-        if ( runcnt < 1 || i + runcnt > n )
-          goto Exit;
-
         /* 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       = FT_GET_BYTE();
+        first      += FT_GET_BYTE();
         points[i++] = first;
 
-        if ( runcnt < 1 || i + runcnt > n )
-          goto Exit;
-
         for ( j = 0; j < runcnt; j++ )
         {
           first      += FT_GET_BYTE();
           points[i++] = first;
+          if ( i >= n )
+            break;
         }
       }
     }
 
-  Exit:
     return points;
   }
 
@@ -212,6 +222,8 @@
   /* <Input>                                                               */
   /*    stream    :: The data stream.                                      */
   /*                                                                       */
+  /*    size      :: The size of the table holding the data.               */
+  /*                                                                       */
   /*    delta_cnt :: The number of deltas to be read.                      */
   /*                                                                       */
   /* <Return>                                                              */
@@ -222,6 +234,7 @@
   /*                                                                       */
   static FT_Short*
   ft_var_readpackeddeltas( FT_Stream  stream,
+                           FT_ULong   size,
                            FT_UInt    delta_cnt )
   {
     FT_Short  *deltas = NULL;
@@ -233,6 +246,12 @@
     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;
 
@@ -341,7 +360,8 @@
       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.   */
@@ -357,8 +377,8 @@
       for ( j = 0; j < segment->pairCount; j++ )
       {
         /* convert to Fixed */
-        segment->correspondence[j].fromCoord = FT_GET_SHORT() << 2;
-        segment->correspondence[j].toCoord   = FT_GET_SHORT() << 2;
+        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,
@@ -447,10 +467,6 @@
     if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
       goto Exit;
 
-    blend->tuplecount  = gvar_head.globalCoordCount;
-    blend->gv_glyphcnt = gvar_head.glyphCount;
-    offsetToData       = gvar_start + gvar_head.offsetToData;
-
     if ( gvar_head.version != 0x00010000L )
     {
       FT_TRACE1(( "bad table version\n" ));
@@ -458,8 +474,6 @@
       goto Exit;
     }
 
-    FT_TRACE2(( "loaded\n" ));
-
     if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
     {
       FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
@@ -468,6 +482,33 @@
       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;
+
     FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
                 blend->tuplecount ));
 
@@ -511,10 +552,10 @@
       for ( i = 0; i < blend->tuplecount; i++ )
       {
         FT_TRACE5(( "  [ " ));
-        for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
+        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 ));
         }
@@ -573,6 +614,11 @@
     {
       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. */
@@ -585,62 +631,74 @@
         continue;
       }
 
-      else if ( blend->normalizedcoords[i] == 0 )
+      if ( blend->normalizedcoords[i] == 0 )
       {
         FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
         apply = 0;
         break;
       }
 
-      else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
-                ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
+      if ( blend->normalizedcoords[i] == tuple_coords[i] )
       {
-        FT_TRACE6(( "      tuple coordinate value %.4f is exceeded, stop\n",
+        FT_TRACE6(( "      tuple coordinate value %.4f fits perfectly\n",
                     tuple_coords[i] / 65536.0 ));
-        apply = 0;
-        break;
+        /* `apply' does not change */
+        continue;
       }
 
-      else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
       {
+        /* not an intermediate tuple */
+
+        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 ));
-        /* 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]   )
-      {
-        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] );
+                           blend->normalizedcoords[i],
+                           tuple_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] );
+        /* 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] );
+        }
       }
     }
 
@@ -698,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.                             */
@@ -1352,13 +1411,25 @@
       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" ));
 
-    FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount ));
+      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++ )
     {
@@ -1378,7 +1449,7 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from        */
+          tuple_coords[j] = FT_GET_SHORT() * 4;  /* convert from        */
                                                  /* short frac to fixed */
       }
       else
@@ -1396,9 +1467,9 @@
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          im_start_coords[j] = FT_GET_SHORT() << 2;
+          im_start_coords[j] = FT_GET_SHORT() * 4;
         for ( j = 0; j < blend->num_axis; j++ )
-          im_end_coords[j] = FT_GET_SHORT() << 2;
+          im_end_coords[j] = FT_GET_SHORT() * 4;
       }
 
       apply = ft_var_apply_tuple( blend,
@@ -1420,8 +1491,11 @@
 
       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 )
@@ -1643,19 +1717,18 @@
   /* modeled after `Ins_IUP */
 
   static void
-  tt_handle_deltas( FT_Outline*  outline,
-                    FT_Vector*   in_points,
-                    FT_Bool*     has_delta )
+  tt_interpolate_deltas( FT_Outline*  outline,
+                         FT_Vector*   out_points,
+                         FT_Vector*   in_points,
+                         FT_Bool*     has_delta )
   {
-    FT_Vector*  out_points;
+    FT_Int  first_point;
+    FT_Int  end_point;
 
-    FT_UInt  first_point;
-    FT_UInt  end_point;
+    FT_Int  first_delta;
+    FT_Int  cur_delta;
 
-    FT_UInt  first_delta;
-    FT_UInt  cur_delta;
-
-    FT_UInt   point;
+    FT_Int    point;
     FT_Short  contour;
 
 
@@ -1663,8 +1736,6 @@
     if ( !outline->n_contours )
       return;
 
-    out_points = outline->points;
-
     contour = 0;
     point   = 0;
 
@@ -1768,6 +1839,7 @@
     GX_Blend    blend  = face->blend;
 
     FT_Vector*  points_org = NULL;
+    FT_Vector*  points_out = NULL;
     FT_Bool*    has_delta  = NULL;
 
     FT_Error    error;
@@ -1799,6 +1871,7 @@
     }
 
     if ( FT_NEW_ARRAY( points_org, n_points ) ||
+         FT_NEW_ARRAY( points_out, n_points ) ||
          FT_NEW_ARRAY( has_delta, n_points )  )
       goto Fail1;
 
@@ -1818,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 )
     {
@@ -1826,13 +1912,19 @@
 
       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 );
     }
 
-    FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount ));
+    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++ )
     {
@@ -1849,11 +1941,14 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_GET_SHORT() << 2;  /* convert from        */
+          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 Fail2;
       }
@@ -1866,9 +1961,9 @@
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          im_start_coords[j] = FT_GET_SHORT() << 2;
+          im_start_coords[j] = FT_GET_SHORT() * 4;
         for ( j = 0; j < blend->num_axis; j++ )
-          im_end_coords[j] = FT_GET_SHORT() << 2;
+          im_end_coords[j] = FT_GET_SHORT() * 4;
       }
 
       apply = ft_var_apply_tuple( blend,
@@ -1885,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
@@ -1899,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 );
 
@@ -1920,22 +2019,20 @@
         /* this means that there are deltas for every point in the glyph */
         for ( j = 0; j < n_points; j++ )
         {
-#ifdef FT_DEBUG_LEVEL_TRACE
-          FT_Vector  point_org = outline->points[j];
-#endif
+          FT_Pos  delta_x = FT_MulFix( deltas_x[j], apply );
+          FT_Pos  delta_y = FT_MulFix( deltas_y[j], apply );
 
 
-          outline->points[j].x += FT_MulFix( deltas_x[j], apply );
-          outline->points[j].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 ( ( point_org.x != outline->points[j].x ) ||
-               ( point_org.y != outline->points[j].y ) )
+          if ( delta_x || delta_y )
           {
             FT_TRACE7(( "      %d: (%d, %d) -> (%d, %d)\n",
                         j,
-                        point_org.x,
-                        point_org.y,
+                        outline->points[j].x - delta_x,
+                        outline->points[j].y - delta_y,
                         outline->points[j].x,
                         outline->points[j].y ));
             count++;
@@ -1960,13 +2057,13 @@
         /* IUP bytecode instruction                                 */
         for ( j = 0; j < n_points; j++ )
         {
-          points_org[j] = outline->points[j];
           has_delta[j]  = FALSE;
+          points_out[j] = points_org[j];
         }
 
         for ( j = 0; j < point_count; j++ )
         {
-          FT_UShort  idx = localpoints[j];
+          FT_UShort  idx = points[j];
 
 
           if ( idx >= n_points )
@@ -1974,34 +2071,43 @@
 
           has_delta[idx] = TRUE;
 
-          outline->points[idx].x += FT_MulFix( deltas_x[j], apply );
-          outline->points[idx].y += FT_MulFix( deltas_y[j], apply );
+          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_handle_deltas( outline,
-                          points_org,
-                          has_delta );
+        tt_interpolate_deltas( outline,
+                               points_out,
+                               points_org,
+                               has_delta );
 
-#ifdef FT_DEBUG_LEVEL_TRACE
         FT_TRACE7(( "    point deltas:\n" ));
 
-        for ( j = 0; j < n_points; j++)
+        for ( j = 0; j < n_points; j++ )
         {
-          if ( ( points_org[j].x != outline->points[j].x ) ||
-               ( points_org[j].y != outline->points[j].y ) )
+          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,
-                        points_org[j].x,
-                        points_org[j].y,
+                        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
@@ -2020,6 +2126,8 @@
     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 );
@@ -2028,6 +2136,7 @@
 
   Fail1:
     FT_FREE( points_org );
+    FT_FREE( points_out );
     FT_FREE( has_delta );
 
     return error;
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 060d4d6..aa8f6ea 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader (specification)                    */
 /*                                                                         */
-/*  Copyright 2004-2015 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;
 
 
@@ -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 089f604..2d15ea7 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2015 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,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
@@ -45,19 +49,21 @@
 #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 )
 
-
-#define SUBPIXEL_HINTING                                                     \
+#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
 
 #define PROJECT( v1, v2 )                                                \
           exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
@@ -74,47 +80,18 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Instruction dispatch function, as used by the interpreter.            */
-  /*                                                                       */
-  typedef void  (*TInstruction_Function)( TT_ExecContext  exc,
-                                          FT_Long*        args );
-
-
-  /*************************************************************************/
-  /*                                                                       */
   /* Two simple bounds-checking macros.                                    */
   /*                                                                       */
 #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
 
 #undef  FAILURE
 #define FAILURE  1
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define GUESS_VECTOR( V )                                             \
-  do                                                                  \
-  {                                                                   \
-    if ( exc->face->unpatented_hinting )                              \
-    {                                                                 \
-      exc->GS.V.x = (FT_F2Dot14)( exc->GS.both_x_axis ? 0x4000 : 0 ); \
-      exc->GS.V.y = (FT_F2Dot14)( exc->GS.both_x_axis ? 0 : 0x4000 ); \
-    }                                                                 \
-  } while (0)
-#else
-#define GUESS_VECTOR( V )  do { } while (0)
-#endif
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -316,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;
@@ -423,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;
 
@@ -563,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;
 
@@ -593,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
@@ -716,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 ),
@@ -799,7 +769,7 @@
     /*  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 ),
@@ -817,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 ),
@@ -1100,8 +1070,13 @@
     "7 INS_$8F",
 
     "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",
@@ -1486,34 +1461,22 @@
   {
     if ( !exc->tt_metrics.ratio )
     {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-      if ( exc->face->unpatented_hinting )
-      {
-        if ( exc->GS.both_x_axis )
-          exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
-        else
-          exc->tt_metrics.ratio = exc->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 ( 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
-        {
-          FT_F26Dot6  x, y;
+        FT_F26Dot6  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 );
-        }
+        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 exc->tt_metrics.ratio;
@@ -1611,7 +1574,7 @@
   static FT_Short
   GetShortIns( TT_ExecContext  exc )
   {
-    /* Reading a byte stream so there is no endianess (DaveP) */
+    /* 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]      );
@@ -1692,6 +1655,10 @@
   /* <InOut>                                                               */
   /*    zone     :: The affected glyph zone.                               */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*    `Touches' the point.                                               */
+  /*                                                                       */
   static void
   Direct_Move( TT_ExecContext  exc,
                TT_GlyphZone    zone,
@@ -1701,19 +1668,28 @@
     FT_F26Dot6  v;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !exc->face->unpatented_hinting );
-#endif
-
     v = exc->GS.freeVector.x;
 
     if ( v != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( !SUBPIXEL_HINTING                                      ||
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY                            &&
            ( !exc->ignore_x_mode                                ||
              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+        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;
@@ -1723,7 +1699,13 @@
 
     if ( v != 0 )
     {
-      zone->cur[point].y += FT_MulDiv( distance, v, exc->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;
     }
@@ -1756,10 +1738,6 @@
     FT_F26Dot6  v;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !exc->face->unpatented_hinting );
-#endif
-
     v = exc->GS.freeVector.x;
 
     if ( v != 0 )
@@ -1778,6 +1756,7 @@
   /*                                                                       */
   /*   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.       */
   /*                                                                       */
   /*************************************************************************/
 
@@ -1788,12 +1767,19 @@
                  FT_UShort       point,
                  FT_F26Dot6      distance )
   {
-    FT_UNUSED( exc );
+#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   ||
-         !exc->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;
@@ -1808,8 +1794,14 @@
   {
     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;
   }
 
 
@@ -2088,7 +2080,7 @@
                         FT_F26Dot6      distance,
                         FT_F26Dot6      compensation )
   {
-    FT_F26Dot6 val;
+    FT_F26Dot6  val;
 
     FT_UNUSED( exc );
 
@@ -2127,7 +2119,7 @@
   /*    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.                                                   */
@@ -2352,10 +2344,6 @@
            FT_Pos          dx,
            FT_Pos          dy )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !exc->face->unpatented_hinting );
-#endif
-
     return TT_DotFix14( dx, dy,
                         exc->GS.projVector.x,
                         exc->GS.projVector.y );
@@ -2457,51 +2445,6 @@
   static void
   Compute_Funcs( TT_ExecContext  exc )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      /* 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.                                */
-      exc->GS.both_x_axis = (FT_Bool)( exc->GS.projVector.x == 0x4000 &&
-                                       exc->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.     */
-      exc->GS.projVector.x = 0;
-      exc->GS.projVector.y = 0;
-      exc->GS.freeVector.x = 0;
-      exc->GS.freeVector.y = 0;
-
-      if ( exc->GS.both_x_axis )
-      {
-        exc->func_project   = Project_x;
-        exc->func_move      = Direct_Move_X;
-        exc->func_move_orig = Direct_Move_Orig_X;
-      }
-      else
-      {
-        exc->func_project   = Project_y;
-        exc->func_move      = Direct_Move_Y;
-        exc->func_move_orig = Direct_Move_Orig_Y;
-      }
-
-      if ( exc->GS.dualVector.x == 0x4000 )
-        exc->func_dualproj = Project_x;
-      else if ( exc->GS.dualVector.y == 0x4000 )
-        exc->func_dualproj = Project_y;
-      else
-        exc->func_dualproj = Dual_Project;
-
-      /* Force recalculation of cached aspect ratio */
-      exc->tt_metrics.ratio = 0;
-
-      return;
-    }
-#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
-
     if ( exc->GS.freeVector.x == 0x4000 )
       exc->F_dot_P = exc->GS.projVector.x;
     else if ( exc->GS.freeVector.y == 0x4000 )
@@ -2580,26 +2523,23 @@
              FT_F26Dot6      Vy,
              FT_UnitVector*  R )
   {
-    FT_F26Dot6  W;
+    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;
   }
@@ -2644,13 +2584,20 @@
   Ins_MPS( TT_ExecContext  exc,
            FT_Long*        args )
   {
-    /* Note: The point size should be irrelevant in a given font program; */
-    /*       we thus decide to return only the PPEM value.                */
-#if 0
-    args[0] = exc->metrics.pointSize;
-#else
-    args[0] = exc->func_cur_ppem( exc );
-#endif
+    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;
+    }
   }
 
 
@@ -2943,7 +2890,7 @@
   /*                                                                       */
   /* NEG[]:        NEGate                                                  */
   /* Opcode range: 0x65                                                    */
-  /* Stack: f26.6 --> f26.6                                                */
+  /* Stack:        f26.6 --> f26.6                                         */
   /*                                                                       */
   static void
   Ins_NEG( FT_Long*  args )
@@ -2988,8 +2935,6 @@
   Ins_RS( TT_ExecContext  exc,
           FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-
     FT_ULong  I = (FT_ULong)args[0];
 
 
@@ -3002,9 +2947,10 @@
     }
     else
     {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* subpixel hinting - avoid Typeman Dstroke and */
       /* IStroke and Vacuform rounds                  */
-      if ( SUBPIXEL_HINTING                            &&
+      if ( SUBPIXEL_HINTING_INFINALITY                 &&
            exc->ignore_x_mode                          &&
            ( ( I == 24                             &&
                ( exc->face->sph_found_func_flags &
@@ -3019,25 +2965,9 @@
                exc->iup_called                     ) ) )
         args[0] = 0;
       else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
         args[0] = exc->storage[I];
     }
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-    FT_ULong  I = (FT_ULong)args[0];
-
-
-    if ( BOUNDSL( I, exc->storeSize ) )
-    {
-      if ( exc->pedantic_hinting )
-        ARRAY_BOUND_ERROR;
-      else
-        args[0] = 0;
-    }
-    else
-      args[0] = exc->storage[I];
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
   }
 
 
@@ -3200,7 +3130,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* MAX[]:        MAXimum                                                 */
-  /* Opcode range: 0x68                                                    */
+  /* Opcode range: 0x8B                                                    */
   /* Stack:        int32? int32? --> int32                                 */
   /*                                                                       */
   static void
@@ -3214,7 +3144,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* MIN[]:        MINimum                                                 */
-  /* Opcode range: 0x69                                                    */
+  /* Opcode range: 0x8C                                                    */
   /* Stack:        int32? int32? --> int32                                 */
   /*                                                                       */
   static void
@@ -3519,7 +3449,7 @@
     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 */
@@ -3617,7 +3547,7 @@
     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! */
@@ -3662,7 +3592,7 @@
     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 )
@@ -3675,9 +3605,9 @@
     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++ )
         {
@@ -3784,7 +3714,7 @@
             ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       switch ( exc->opcode )
       {
@@ -3813,9 +3743,9 @@
     TT_CallRec*  pRec;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     exc->sph_in_func_flags = 0x0000;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->callTop <= 0 )     /* We encountered an ENDF without a call */
     {
@@ -3901,8 +3831,8 @@
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                               &&
+#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 ) ) ||
@@ -3910,7 +3840,7 @@
       goto Fail;
     else
       exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check the call stack */
     if ( exc->callTop >= exc->callSize )
@@ -3989,14 +3919,14 @@
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                    &&
+#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
       exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check stack */
     if ( exc->callTop >= exc->callSize )
@@ -4089,6 +4019,7 @@
         exc->error = FT_THROW( Nested_DEFS );
         return;
       case 0x2D:   /* ENDF */
+        def->end = exc->IP;
         return;
       }
     }
@@ -4308,16 +4239,12 @@
       exc->GS.dualVector.x = AA;
       exc->GS.dualVector.y = BB;
     }
-    else
-      GUESS_VECTOR( projVector );
 
     if ( ( opcode & 2 ) == 0 )
     {
       exc->GS.freeVector.x = AA;
       exc->GS.freeVector.y = BB;
     }
-    else
-      GUESS_VECTOR( freeVector );
 
     Compute_Funcs( exc );
   }
@@ -4339,7 +4266,6 @@
                     &exc->GS.projVector ) == SUCCESS )
     {
       exc->GS.dualVector = exc->GS.projVector;
-      GUESS_VECTOR( freeVector );
       Compute_Funcs( exc );
     }
   }
@@ -4360,7 +4286,6 @@
                     (FT_UShort)args[0],
                     &exc->GS.freeVector ) == SUCCESS )
     {
-      GUESS_VECTOR( projVector );
       Compute_Funcs( exc );
     }
   }
@@ -4375,7 +4300,6 @@
   static void
   Ins_SFVTPV( TT_ExecContext  exc )
   {
-    GUESS_VECTOR( projVector );
     exc->GS.freeVector = exc->GS.projVector;
     Compute_Funcs( exc );
   }
@@ -4404,7 +4328,6 @@
     Normalize( X, Y, &exc->GS.projVector );
 
     exc->GS.dualVector = exc->GS.projVector;
-    GUESS_VECTOR( freeVector );
     Compute_Funcs( exc );
   }
 
@@ -4430,7 +4353,6 @@
     X = S;
 
     Normalize( X, Y, &exc->GS.freeVector );
-    GUESS_VECTOR( projVector );
     Compute_Funcs( exc );
   }
 
@@ -4445,21 +4367,8 @@
   Ins_GPV( TT_ExecContext  exc,
            FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      args[0] = exc->GS.both_x_axis ? 0x4000 : 0;
-      args[1] = exc->GS.both_x_axis ? 0 : 0x4000;
-    }
-    else
-    {
-      args[0] = exc->GS.projVector.x;
-      args[1] = exc->GS.projVector.y;
-    }
-#else
     args[0] = exc->GS.projVector.x;
     args[1] = exc->GS.projVector.y;
-#endif
   }
 
 
@@ -4473,21 +4382,8 @@
   Ins_GFV( TT_ExecContext  exc,
            FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      args[0] = exc->GS.both_x_axis ? 0x4000 : 0;
-      args[1] = exc->GS.both_x_axis ? 0 : 0x4000;
-    }
-    else
-    {
-      args[0] = exc->GS.freeVector.x;
-      args[1] = exc->GS.freeVector.y;
-    }
-#else
     args[0] = exc->GS.freeVector.x;
     args[1] = exc->GS.freeVector.y;
-#endif
   }
 
 
@@ -4607,7 +4503,7 @@
   /*                                                                       */
   /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
   /* Opcode range: 0x4E                                                    */
-  /* Stack: -->                                                            */
+  /* Stack:        -->                                                     */
   /*                                                                       */
   static void
   Ins_FLIPOFF( TT_ExecContext  exc )
@@ -4926,13 +4822,13 @@
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
-    if ( SUBPIXEL_HINTING   &&
-         exc->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;
   }
@@ -5017,7 +4913,6 @@
     }
 
     Normalize( A, B, &exc->GS.projVector );
-    GUESS_VECTOR( freeVector );
     Compute_Funcs( exc );
   }
 
@@ -5157,11 +5052,11 @@
   Ins_INSTCTRL( TT_ExecContext  exc,
                 FT_Long*        args )
   {
-    FT_Long  K, L, Kf;
+    FT_ULong  K, L, Kf;
 
 
-    K = args[1];
-    L = args[0];
+    K = (FT_ULong)args[1];
+    L = (FT_ULong)args[0];
 
     /* selector values cannot be `OR'ed;                 */
     /* they are indices starting with index 1, not flags */
@@ -5189,12 +5084,23 @@
     exc->GS.instruct_control &= ~(FT_Byte)Kf;
     exc->GS.instruct_control |= (FT_Byte)L;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    /* INSTCTRL modifying flag 3 also has an effect */
-    /* outside of the CVT program                   */
     if ( K == 3 )
-      exc->ignore_x_mode = FT_BOOL( L == 4 );
+    {
+#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
+    }
   }
 
 
@@ -5279,6 +5185,15 @@
     FT_UShort  point;
 
 
+#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 ( exc->top < exc->GS.loop )
     {
       if ( exc->pedantic_hinting )
@@ -5325,6 +5240,15 @@
     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];
 
@@ -5354,6 +5278,15 @@
     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];
 
@@ -5406,31 +5339,14 @@
 
     d = PROJECT( zp.cur + p, zp.org + p );
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      if ( exc->GS.both_x_axis )
-      {
-        *x = d;
-        *y = 0;
-      }
-      else
-      {
-        *x = 0;
-        *y = d;
-      }
-    }
-    else
-#endif
-    {
-      *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 );
-    }
+    *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( TT_ExecContext  exc,
                   FT_UShort       point,
@@ -5438,35 +5354,28 @@
                   FT_F26Dot6      dy,
                   FT_Bool         touch )
   {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      if ( exc->GS.both_x_axis )
-      {
-        exc->zp2.cur[point].x += dx;
-        if ( touch )
-          exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
-      }
-      else
-      {
-        exc->zp2.cur[point].y += dy;
-        if ( touch )
-          exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
-      }
-      return;
-    }
-#endif
-
     if ( exc->GS.freeVector.x != 0 )
     {
-      exc->zp2.cur[point].x += dx;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility ) )
+#endif
+        exc->zp2.cur[point].x += dx;
+
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
 
     if ( exc->GS.freeVector.y != 0 )
     {
-      exc->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 )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -5513,13 +5422,12 @@
         }
       }
       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   &&
-           exc->ignore_x_mode )
+      if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode )
         Move_Zp2_Point( exc, point, 0, dy, TRUE );
       else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
         Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
       exc->GS.loop--;
@@ -5647,9 +5555,15 @@
   {
     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 ( exc->top < exc->GS.loop + 1 )
@@ -5659,26 +5573,8 @@
       goto Fail;
     }
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( exc->face->unpatented_hinting )
-    {
-      if ( exc->GS.both_x_axis )
-      {
-        dx = (FT_UInt32)args[0];
-        dy = 0;
-      }
-      else
-      {
-        dx = 0;
-        dy = (FT_UInt32)args[0];
-      }
-    }
-    else
-#endif
-    {
-      dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
-      dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
-    }
+    dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
+    dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
 
     while ( exc->GS.loop > 0 )
     {
@@ -5695,7 +5591,8 @@
         }
       }
       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.              */
@@ -5705,8 +5602,7 @@
         /*   - the glyph is specifically set to allow SHPIX moves        */
         /*   - the move is on a previously Y-touched point               */
 
-        if ( SUBPIXEL_HINTING   &&
-             exc->ignore_x_mode )
+        if ( exc->ignore_x_mode )
         {
           /* save point for later comparison */
           if ( exc->GS.freeVector.y != 0 )
@@ -5770,15 +5666,30 @@
         else
           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( exc, point, dx, dy, TRUE );
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
+#endif
       exc->GS.loop--;
     }
 
@@ -5798,14 +5709,13 @@
   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 = exc->GS.control_value_cutin;
 
@@ -5814,8 +5724,7 @@
            !( 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];
 
@@ -5838,14 +5747,14 @@
 
     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                                    &&
+    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 */
 
     exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
@@ -5884,10 +5793,10 @@
     if ( ( exc->opcode & 1 ) != 0 )
     {
       cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+#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,
@@ -5930,14 +5839,14 @@
     cvtEntry            = (FT_ULong)args[1];
     point               = (FT_UShort)args[0];
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#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,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
@@ -5971,27 +5880,27 @@
 
     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                      ||
-           ( !exc->ignore_x_mode                ||
-             !exc->face->sph_compatibility_mode ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      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                               &&
+#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 = FAST_PROJECT( &exc->zp0.cur[point] );
 
@@ -6000,10 +5909,10 @@
       if ( FT_ABS( distance - org_dist ) > control_value_cutin )
         distance = org_dist;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 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] );
@@ -6032,19 +5941,19 @@
   Ins_MDRP( TT_ExecContext  exc,
             FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  org_dist, distance, minimum_distance;
 
 
     minimum_distance = exc->GS.minimum_distance;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#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];
 
@@ -6108,10 +6017,10 @@
 
     if ( ( exc->opcode & 4 ) != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+#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,
@@ -6179,11 +6088,11 @@
                 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    = exc->GS.minimum_distance;
@@ -6191,13 +6100,13 @@
     point               = (FT_UShort)args[0];
     cvtEntry            = (FT_ULong)( args[1] + 1 );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#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 */
 
@@ -6250,8 +6159,8 @@
         cvt_dist = -cvt_dist;
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+#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 ) )
@@ -6261,7 +6170,7 @@
       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 */
 
@@ -6296,16 +6205,16 @@
     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             &&
+      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(
                    exc,
@@ -6329,8 +6238,8 @@
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
       B1 = exc->zp1.cur[point].y;
 
@@ -6347,12 +6256,12 @@
            ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
         distance += 64;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     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 = exc->zp1.cur[point].y;
 
@@ -6376,7 +6285,7 @@
         exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   Fail:
     exc->GS.rp1 = exc->GS.rp0;
@@ -6401,8 +6310,8 @@
     FT_F26Dot6  distance;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+#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 ) )
@@ -6410,7 +6319,7 @@
       exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->top < exc->GS.loop                  ||
          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
@@ -6505,8 +6414,6 @@
     dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
     dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
 
-    exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
-
     discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
                    FT_MulDiv( day, dbx, 0x40 );
     dotproduct   = FT_MulDiv( dax, dbx, 0x40 ) +
@@ -6527,6 +6434,7 @@
       R.x = FT_MulDiv( val, dax, discriminant );
       R.y = FT_MulDiv( val, day, discriminant );
 
+      /* 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;
     }
@@ -6534,6 +6442,7 @@
     {
       /* else, take the middle of the middles of A and B */
 
+      /* 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 +
@@ -6543,6 +6452,8 @@
                                 exc->zp0.cur[b0].y +
                                 exc->zp0.cur[b1].y ) / 4;
     }
+
+    exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
   }
 
 
@@ -6920,6 +6831,23 @@
     FT_Short  contour;       /* current contour */
 
 
+#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 ( exc->pts.n_contours == 0 )
       return;
@@ -6943,15 +6871,15 @@
     contour = 0;
     point   = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING   &&
-         exc->ignore_x_mode )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         exc->ignore_x_mode          )
     {
       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
     {
@@ -7023,37 +6951,16 @@
     FT_UShort  A;
     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                                         &&
+    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 */
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( exc->face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( exc->args < n )
-      {
-        if ( exc->pedantic_hinting )
-          exc->error = FT_THROW( Too_Few_Arguments );
-        n = exc->args;
-      }
-
-      exc->args -= n;
-      exc->new_top = exc->args;
-      return;
-    }
-#endif
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
@@ -7107,9 +7014,9 @@
             B++;
           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
@@ -7166,9 +7073,25 @@
             }
           }
           else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-            exc->func_move( exc, &exc->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
@@ -7196,26 +7119,6 @@
     FT_Long   B;
 
 
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( exc->face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( exc->args < n )
-      {
-        if ( exc->pedantic_hinting )
-          exc->error = FT_THROW( Too_Few_Arguments );
-        n = exc->args;
-      }
-
-      exc->args -= n;
-      exc->new_top = exc->args;
-      return;
-    }
-#endif
-
     P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];
 
@@ -7304,20 +7207,21 @@
   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  &&
-         exc->subpixel_hinting )
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         ( args[0] & 1 ) != 0        &&
+         exc->subpixel_hinting       )
     {
       if ( exc->ignore_x_mode )
       {
@@ -7331,9 +7235,9 @@
         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                */
@@ -7341,7 +7245,7 @@
     /* Return Bit(s): 8             */
     /*                              */
     if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
-      K |= 0x80;
+      K |= 1 << 8;
 
     /********************************/
     /* GLYPH STRETCHED              */
@@ -7349,19 +7253,83 @@
     /* Return Bit(s): 9             */
     /*                              */
     if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
-      K |= 1 << 8;
+      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 && 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                                     &&
+      /********************************/
+      /* 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 )
     {
 
@@ -7434,12 +7402,63 @@
       }
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = K;
   }
 
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* 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 )
   {
@@ -7516,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 */
                   {
@@ -7527,12 +7546,27 @@
     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_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     exc->iup_called = FALSE;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#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
 
     /* set PPEM and CVT functions */
     exc->tt_metrics.ratio = 0;
@@ -7575,7 +7609,7 @@
                               ? 2
                               : 12 - ( *opcode_name[exc->opcode] - '0' ),
                               "#" ));
-        for ( n = 0; n < cnt; n++ )
+        for ( n = 1; n <= cnt; n++ )
           FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
         FT_TRACE6(( "\n" ));
       }
@@ -7611,7 +7645,21 @@
         exc->args = 0;
       }
 
-      exc->new_top = exc->args + ( Pop_Push_Count[exc->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'  */
@@ -7625,9 +7673,9 @@
       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++ )
         {
@@ -7656,7 +7704,7 @@
         }
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         FT_Long*  args   = exc->stack + exc->args;
@@ -7804,7 +7852,7 @@
           Ins_ALIGNPTS( exc, args );
           break;
 
-        case 0x28:  /* ???? */
+        case 0x28:  /* RAW */
           Ins_UNKNOWN( exc );
           break;
 
@@ -8156,10 +8204,33 @@
           Ins_INSTCTRL( exc, args );
           break;
 
-        case 0x8F:
+        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( exc, args );
@@ -8240,7 +8311,7 @@
 
       /* 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_:
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 32706d0..53f0944 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (specification).                       */
 /*                                                                         */
-/*  Copyright 1996-2015 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"
@@ -99,7 +99,7 @@
   } TT_CallRec, *TT_CallStack;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -138,7 +138,7 @@
 
   } SPH_Font_Class;
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
   /*************************************************************************/
@@ -170,6 +170,7 @@
                        pts,
                        twilight;
 
+    FT_Long            pointSize;  /* in 26.6 format */
     FT_Size_Metrics    metrics;
     TT_Size_Metrics    tt_metrics; /* size metrics */
 
@@ -247,9 +248,135 @@
     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_hinting;  /* Using subpixel hinting?       */
@@ -279,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;
 
@@ -382,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 202aa04..ed3be2d 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (body).                                              */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -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] = {
@@ -270,6 +266,11 @@
         { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
         { 0x13A42602UL, 0x0000007EUL }  /* prep */
       },
+      { /* DFKaiShu2 */
+        { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
+        { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
+        { 0x13A42602UL, 0x0000007EUL }  /* prep */
+      },
       { /* HuaTianKaiTi */
         { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
         { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
@@ -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 );
@@ -1029,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 )
@@ -1252,10 +1287,12 @@
 
     TT_Driver  driver = (TT_Driver)ttdriver;
 
-#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 */
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 7ac4123..98ad383 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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;
@@ -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  */
@@ -430,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 242a6b7..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-2015 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 48ba4aa..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-2015 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 fb338bd..ca158ac 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2015 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,       */
@@ -124,8 +124,9 @@
         TT_Table  entry = face->dir_tables;
         TT_Table  limit = entry + face->num_tables;
 
-        FT_Long   pos  = (FT_Long)FT_STREAM_POS();
-        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 */
@@ -135,10 +136,13 @@
 
 
           if ( diff > 0 && diff < dist )
-            dist = diff;
+          {
+            dist  = diff;
+            found = 1;
+          }
         }
 
-        if ( entry == limit )
+        if ( !found )
         {
           /* `loca' is the last table */
           dist = (FT_Long)stream->size - pos;
@@ -152,6 +156,14 @@
           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;
diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h
index bc92369..aa2e38e 100644
--- a/src/truetype/ttpload.h
+++ b/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2015 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 dbda4d9..0395096 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Subpixel Hinting.                                           */
 /*                                                                         */
-/*  Copyright 2010-2015 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
 
   /*************************************************************************/
   /*                                                                       */
@@ -903,7 +903,7 @@
   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;
     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 9151aa3..86844da 100644
--- a/src/truetype/ttsubpix.h
+++ b/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Subpixel Hinting.                                           */
 /*                                                                         */
-/*  Copyright 2010-2015 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
 
   /*************************************************************************/
   /*                                                                       */
@@ -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 */