Rebased against master for the change to the property setter.
>From c2fa5d7b9193b045dc16e8ccc20bcb2f28b206c3 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Sat, 30 Apr 2016 22:53:01 +0200
Subject: [PATCH 1/3] Prepare landing of new minimal TrueType subpixel hinting
 code (v40).

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.
---
 devel/ftoption.h                    |  67 +++++++++++----
 include/freetype/config/ftoption.h  |  67 +++++++++++----
 include/freetype/ftcffdrv.h         |   8 +-
 include/freetype/ftttdrv.h          |  48 +++++++----
 include/freetype/internal/tttypes.h |   4 +-
 src/truetype/ttdriver.c             |   5 +-
 src/truetype/ttgload.c              | 159 +++++++++++++++++++++++++++---------
 src/truetype/ttinterp.h             | 138 +++++++++++++++++++++++++++++--
 src/truetype/ttobjs.c               |   8 +-
 src/truetype/ttsubpix.c             |   6 +-
 src/truetype/ttsubpix.h             |   4 +-
 11 files changed, 408 insertions(+), 106 deletions(-)

diff --git a/devel/ftoption.h b/devel/ftoption.h
index b354efd..d145eeb 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -585,24 +585,55 @@ FT_BEGIN_HEADER
 
   /*************************************************************************/
   /*                                                                       */
-  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
-  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
-  /* replaces the native TrueType hinting mechanism when anything but      */
-  /* FT_RENDER_MODE_MONO is requested.                                     */
-  /*                                                                       */
-  /* Enabling this causes the TrueType driver to ignore instructions under */
-  /* certain conditions.  This is done in accordance with the guide here,  */
-  /* with some minor differences:                                          */
+  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile         */
+  /* subpixel hinting support into the TrueType driver.  This modifies the */
+  /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is   */
+  /* requested.                                                            */
+  /*                                                                       */
+  /* 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.                                  */
+  /*                                                                       */
+  /* There are three options.                                                */
+  /*                                                                       */
+  /* - 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.                                                             */
+  /*                                                                       */
+  /* - 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.                                */
+  /*
+   * - 3: Compile both. */
   /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /* 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.                                              */
   /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
+  /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be      */
+  /* defined.                                                              */
   /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
   /*                                                                       */
-#define TT_CONFIG_OPTION_SUBPIXEL_HINTING
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 | 2 */
 
 
   /*************************************************************************/
@@ -811,6 +842,14 @@ FT_BEGIN_HEADER
    */
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 #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
 
 
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index a8097fe..a29567b 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -585,24 +585,55 @@ FT_BEGIN_HEADER
 
   /*************************************************************************/
   /*                                                                       */
-  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
-  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
-  /* replaces the native TrueType hinting mechanism when anything but      */
-  /* FT_RENDER_MODE_MONO is requested.                                     */
-  /*                                                                       */
-  /* Enabling this causes the TrueType driver to ignore instructions under */
-  /* certain conditions.  This is done in accordance with the guide here,  */
-  /* with some minor differences:                                          */
+  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile         */
+  /* subpixel hinting support into the TrueType driver.  This modifies the */
+  /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is   */
+  /* requested.                                                            */
+  /*                                                                       */
+  /* 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.                                  */
+  /*                                                                       */
+  /* There are three options.                                                */
+  /*                                                                       */
+  /* - 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.                                                             */
+  /*                                                                       */
+  /* - 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.                                */
+  /*
+   * - 3: Compile both. */
   /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /* 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.                                              */
   /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
+  /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be      */
+  /* defined.                                                              */
   /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
   /*                                                                       */
-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 | 2 */
 
 
   /*************************************************************************/
@@ -811,6 +842,14 @@ FT_BEGIN_HEADER
    */
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 #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
 
 
diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h
index b0b4299..ad34541 100644
--- a/include/freetype/ftcffdrv.h
+++ b/include/freetype/ftcffdrv.h
@@ -110,7 +110,7 @@ FT_BEGIN_HEADER
    *   to minimize distortion.
    *
    * @order:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *   no-stem-darkening[cff]
    *   darkening-parameters[cff]
    *
@@ -120,7 +120,7 @@ FT_BEGIN_HEADER
   /**************************************************************************
    *
    * @property:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *
    * @description:
    *   Thanks to Adobe, which contributed a new hinting (and parsing)
@@ -157,8 +157,8 @@ FT_BEGIN_HEADER
    *   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 ::
diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h
index 6c02e65..e61ee85 100644
--- a/include/freetype/ftttdrv.h
+++ b/include/freetype/ftttdrv.h
@@ -138,31 +138,36 @@ FT_BEGIN_HEADER
    *   interpreter-version
    *
    * @description:
-   *   Currently, two versions are available, representing the bytecode
-   *   interpreter with and without subpixel hinting support,
+   *   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).
+   *   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
+   *   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) font-specific tweaks.
+   *   (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 in the chosen
+   *   interpreter, it simply ignores instructions on vertical stems to arrive
+   *   at very similar results.
    *
-   *   The following example code demonstrates how to activate subpixel
+   *   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_38;
+   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_35;
    *
    *
    *     FT_Init_FreeType( &library );
@@ -199,7 +204,15 @@ FT_BEGIN_HEADER
    *     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).
+   *     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
@@ -207,9 +220,9 @@ FT_BEGIN_HEADER
    *   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.
+   *   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
@@ -290,13 +303,14 @@ FT_BEGIN_HEADER
    *   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.
+   *   Keep in mind that the features of 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
 
  /* */
 
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 8f1a642..4110d50 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1386,12 +1386,12 @@ FT_BEGIN_HEADER
     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 */
 
   } TT_FaceRec;
 
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index abbd127..c9d4081 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -73,9 +73,12 @@
 
 
       if ( *interpreter_version == TT_INTERPRETER_VERSION_35
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#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
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index c4038ee..517b5aa 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -122,7 +122,7 @@
                   FT_UInt    glyph_index )
   {
     TT_Face    face   = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
@@ -153,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                                             )
     {
@@ -165,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 )
     {
@@ -733,7 +733,8 @@
   TT_Hint_Glyph( TT_Loader  loader,
                  FT_Bool    is_composite )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#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
@@ -816,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 )
@@ -831,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,7 +908,7 @@
     }
 
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       TT_Face    face   = loader->face;
       TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 
@@ -916,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 )
       {
@@ -947,7 +958,7 @@
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         /* scale the glyph */
@@ -1078,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;
@@ -1324,7 +1335,8 @@
    * (3) for everything else.
    *
    */
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+   /* XXX merge infinality + lean datafields? */
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
 #define TT_LOADER_SET_PP( loader )                                          \
           do                                                                \
@@ -1350,7 +1362,7 @@
             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
           } while ( 0 )
 
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 #define TT_LOADER_SET_PP( loader )                                          \
           do                                                                \
@@ -1366,7 +1378,7 @@
             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
           } while ( 0 )
 
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
   /*************************************************************************/
@@ -1946,7 +1958,8 @@
                          FT_UInt    glyph_index )
   {
     TT_Face    face   = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY      || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
@@ -1973,11 +1986,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 */
-    /* unless FT_LOAD_COMPUTE_METRICS is set                         */
-    if ( !face->postscript.isFixedPitch                    &&
-         IS_HINTED( loader->load_flags )                   &&
-         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
+    /* 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;
 
@@ -1986,7 +2006,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 )
       {
@@ -2004,7 +2024,7 @@
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         if ( widthp )
@@ -2193,6 +2213,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;
@@ -2206,11 +2230,13 @@
     if ( IS_HINTED( load_flags ) && !glyf_table_only )
     {
       TT_ExecContext  exec;
-      FT_Bool         grayscale;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+      FT_Bool         grayscale = TRUE;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      FT_Bool         subpixel_hinting_lean;
+      FT_Bool         grayscale_cleartype;
+#endif
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       FT_Bool  subpixel_hinting = FALSE;
 
 #if 0
@@ -2222,7 +2248,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;
 
@@ -2243,7 +2269,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 )
       {
@@ -2300,18 +2345,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 )
       {
@@ -2339,9 +2389,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 )
@@ -2374,10 +2452,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
 
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index e5a02b9..5aaceea 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -99,7 +99,7 @@ FT_BEGIN_HEADER
   } TT_CallRec, *TT_CallStack;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -138,7 +138,7 @@ FT_BEGIN_HEADER
 
   } SPH_Font_Class;
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
   /*************************************************************************/
@@ -247,9 +247,135 @@ FT_BEGIN_HEADER
     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? */
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_Bool            grayscale;      /* bi-level hinting and */
+                                       /* grayscale rendering  */
+
+#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' that 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' that 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 +405,7 @@ FT_BEGIN_HEADER
     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;
 
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index a05f216..ed3be2d 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1287,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/ttsubpix.c b/src/truetype/ttsubpix.c
index 5a8f262..0395096 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -27,7 +27,7 @@
 #include "ttsubpix.h"
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -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 6313baa..86844da 100644
--- a/src/truetype/ttsubpix.h
+++ b/src/truetype/ttsubpix.h
@@ -27,7 +27,7 @@
 FT_BEGIN_HEADER
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -100,7 +100,7 @@ FT_BEGIN_HEADER
 #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
-- 
2.5.5

>From c0dd279bf9140da3911054d46cc01e5a4cd99559 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Sat, 30 Apr 2016 22:54:30 +0200
Subject: [PATCH 2/3] Implement new minimal TrueType subpixel hinting code
 (v40).

---
 src/truetype/ttinterp.c | 575 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 394 insertions(+), 181 deletions(-)

diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 78c35f2..25cb817 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -45,10 +45,21 @@
 #define FT_COMPONENT  trace_ttinterp
 
 
-#define SUBPIXEL_HINTING                                                     \
+#define NO_SUBPIXEL_HINTING                                                  \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_35 )
+
+#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 )
@@ -286,8 +297,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;
@@ -1642,6 +1653,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,
@@ -1655,11 +1670,24 @@
 
     if ( v != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( !SUBPIXEL_HINTING                                      ||
-           ( !exc->ignore_x_mode                                ||
-             ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
-#endif /* TT_CONFIG_OPTION_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 ) ) )
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      else
+#endif /* 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;
@@ -1669,7 +1697,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;
     }
@@ -1720,6 +1754,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.       */
   /*                                                                       */
   /*************************************************************************/
 
@@ -1730,12 +1765,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 /* SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
+      zone->cur[point].x += distance;
+    else
+#endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( !SUBPIXEL_HINTING   ||
-         !exc->ignore_x_mode )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    if ( NO_SUBPIXEL_HINTING )
       zone->cur[point].x += distance;
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
@@ -1750,8 +1792,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;
   }
 
 
@@ -1853,16 +1901,17 @@
   /* <Return>                                                              */
   /*    Rounded distance.                                                  */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_To_Grid( TT_ExecContext  exc,
                  FT_F26Dot6      distance,
                  FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
-
     FT_UNUSED( exc );
 
-
     if ( distance >= 0 )
     {
       val = FT_PIX_ROUND( distance + compensation );
@@ -1896,13 +1945,15 @@
   /* <Return>                                                              */
   /*    Rounded distance.                                                  */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_To_Half_Grid( TT_ExecContext  exc,
                       FT_F26Dot6      distance,
                       FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
-
     FT_UNUSED( exc );
 
 
@@ -1939,13 +1990,15 @@
   /* <Return>                                                              */
   /*    Rounded distance.                                                  */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_Down_To_Grid( TT_ExecContext  exc,
                       FT_F26Dot6      distance,
                       FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
-
     FT_UNUSED( exc );
 
 
@@ -1982,13 +2035,15 @@
   /* <Return>                                                              */
   /*    Rounded distance.                                                  */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_Up_To_Grid( TT_ExecContext  exc,
                     FT_F26Dot6      distance,
                     FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
-
     FT_UNUSED( exc );
 
 
@@ -2025,13 +2080,15 @@
   /* <Return>                                                              */
   /*    Rounded distance.                                                  */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_To_Double_Grid( TT_ExecContext  exc,
                         FT_F26Dot6      distance,
                         FT_F26Dot6      compensation )
   {
-    FT_F26Dot6 val;
-
+    FT_F26Dot6  val;
     FT_UNUSED( exc );
 
 
@@ -2069,17 +2126,20 @@
   /*    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.                                                   */
   /*                                                                       */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_Super( TT_ExecContext  exc,
                FT_F26Dot6      distance,
                FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
@@ -2123,12 +2183,15 @@
   /*    There is a separate function for Round_Super_45() as we may need   */
   /*    greater precision.                                                 */
   /*                                                                       */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*                                                                       */
   static FT_F26Dot6
   Round_Super_45( TT_ExecContext  exc,
                   FT_F26Dot6      distance,
                   FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+    FT_UNUSED( exc );
 
 
     if ( distance >= 0 )
@@ -2878,8 +2941,6 @@
   Ins_RS( TT_ExecContext  exc,
           FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-
     FT_ULong  I = (FT_ULong)args[0];
 
 
@@ -2892,10 +2953,11 @@
     }
     else
     {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* subpixel hinting - avoid Typeman Dstroke and */
       /* IStroke and Vacuform rounds                  */
-      if ( SUBPIXEL_HINTING                            &&
-           exc->ignore_x_mode                          &&
+      if ( SUBPIXEL_HINTING_INFINALITY               &&
+           exc->ignore_x_mode                        &&
            ( ( I == 24                             &&
                ( exc->face->sph_found_func_flags &
                  ( SPH_FDEF_SPACING_1 |
@@ -2906,28 +2968,12 @@
              ( I == 8                              &&
                ( exc->face->sph_found_func_flags &
                  SPH_FDEF_VACUFORM_ROUND_1       ) &&
-               exc->iup_called                     ) ) )
+             exc->iup_called                     ) ) )
         args[0] = 0;
       else
+#endif /* !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 */
   }
 
 
@@ -3409,7 +3455,8 @@
     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 */
@@ -3507,7 +3554,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 /* SUBPIXEL_HINTING_INFINALITY */
 
 
     /* some font programs are broken enough to redefine functions! */
@@ -3552,7 +3599,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 )
@@ -3565,9 +3612,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++ )
         {
@@ -3674,7 +3721,7 @@
             ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
       switch ( exc->opcode )
       {
@@ -3703,9 +3750,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->callTop <= 0 )     /* We encountered an ENDF without a call */
     {
@@ -3791,16 +3838,16 @@
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                               &&
-         exc->ignore_x_mode                                             &&
-         ( ( exc->iup_called                                        &&
-             ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
-           ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )        ) )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                                   &&
+        exc->ignore_x_mode                                             &&
+        ( ( exc->iup_called                                        &&
+            ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
+          ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )        ) )
       goto Fail;
     else
       exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     /* check the call stack */
     if ( exc->callTop >= exc->callSize )
@@ -3879,14 +3926,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     /* check stack */
     if ( exc->callTop >= exc->callSize )
@@ -4781,13 +4828,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = D;
   }
@@ -5011,7 +5058,7 @@
   Ins_INSTCTRL( TT_ExecContext  exc,
                 FT_Long*        args )
   {
-    FT_ULong  K, L, Kf;
+    FT_ULong   K, L, Kf;
 
 
     K = (FT_ULong)args[1];
@@ -5043,12 +5090,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
+    }
   }
 
 
@@ -5133,6 +5191,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 )
@@ -5179,6 +5246,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];
 
@@ -5208,6 +5284,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];
 
@@ -5267,6 +5352,7 @@
   }
 
 
+  /* See `ttinterp.h' for details on backwards compatibility mode. */
   static void
   Move_Zp2_Point( TT_ExecContext  exc,
                   FT_UShort       point,
@@ -5276,14 +5362,26 @@
   {
     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;
     }
@@ -5330,13 +5428,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 /* SUBPIXEL_HINTING_INFINALITY */
         Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
       exc->GS.loop--;
@@ -5464,7 +5561,7 @@
   {
     FT_F26Dot6  dx, dy;
     FT_UShort   point;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Int      B1, B2;
 #endif
 
@@ -5494,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.              */
@@ -5504,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 )
@@ -5569,15 +5666,26 @@
         else
           Move_Zp2_Point( exc, point, dx, dy, TRUE );
       }
+      else
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( SUBPIXEL_HINTING_MINIMAL &&
+           exc->backwards_compatibility                 )
+      {
+        /* XXX: breaks Rokkitt < v1.2                   */
+        /*      (glyphs explode vertically on ALIGNRP). */
+        if ( !( 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--;
     }
 
@@ -5597,14 +5705,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;
 
@@ -5613,8 +5720,7 @@
            !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
         control_value_cutin = 0;
     }
-
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
@@ -5637,14 +5743,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
@@ -5683,10 +5789,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,
@@ -5729,14 +5835,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     if ( BOUNDS( point,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
@@ -5770,27 +5876,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                      ||
+      if ( SUBPIXEL_HINTING_INFINALITY          &&
            ( !exc->ignore_x_mode                ||
              !exc->face->sph_compatibility_mode ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* 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                               &&
-         exc->ignore_x_mode                             &&
-         ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
-         distance > 0                                   &&
-         exc->GS.freeVector.y != 0                      )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
+         exc->ignore_x_mode                                 &&
+         ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK )     &&
+         distance > 0                                       &&
+         exc->GS.freeVector.y != 0                          )
       distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
 
@@ -5799,10 +5905,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] );
@@ -5831,19 +5937,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
@@ -5907,10 +6013,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,
@@ -5978,11 +6084,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 /* SUBPIXEL_HINTING_INFINALITY */
 
 
     minimum_distance    = exc->GS.minimum_distance;
@@ -5990,13 +6096,14 @@
     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 */
+    else
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
@@ -6049,8 +6156,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 ) )
@@ -6060,7 +6167,7 @@
       else if ( cur_dist > 64 && cur_dist < 84 )
         cvt_dist += 32;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     /* control value cut-in and round */
 
@@ -6095,16 +6202,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             &&
-           exc->ignore_x_mode           &&
-           exc->GS.gep0 == exc->GS.gep1 )
+      if ( SUBPIXEL_HINTING_INFINALITY                                   &&
+           exc->ignore_x_mode                                 &&
+           exc->GS.gep0 == exc->GS.gep1                       )
       {
         if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
           cvt_dist = org_dist;
       }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
       distance = Round_None(
                    exc,
@@ -6128,8 +6235,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;
 
@@ -6146,12 +6253,12 @@
            ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
         distance += 64;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* 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;
 
@@ -6175,7 +6282,7 @@
         exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
   Fail:
     exc->GS.rp1 = exc->GS.rp0;
@@ -6200,8 +6307,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 ) )
@@ -6209,7 +6316,7 @@
       exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->top < exc->GS.loop                  ||
          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
@@ -6324,6 +6431,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;
     }
@@ -6331,6 +6439,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 +
@@ -6719,6 +6828,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;
@@ -6742,15 +6868,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 /* SUBPIXEL_HINTING_INFINALITY */
 
     do
     {
@@ -6822,16 +6948,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 */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
@@ -6885,9 +7011,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
@@ -6944,9 +7070,25 @@
             }
           }
           else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* 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
@@ -7062,20 +7204,23 @@
   Ins_GETINFO( TT_ExecContext  exc,
                FT_Long*        args )
   {
-    FT_Long  K;
+    FT_Long    K;
+    TT_Driver  driver;
 
 
     K = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+
+#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 )
       {
@@ -7089,9 +7234,9 @@
         K = TT_INTERPRETER_VERSION_38;
     }
     else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
       if ( ( args[0] & 1 ) != 0 )
-        K = TT_INTERPRETER_VERSION_35;
+        K = driver->interpreter_version;
 
     /********************************/
     /* GLYPH ROTATED                */
@@ -7110,16 +7255,69 @@
       K |= 1 << 8;
 
     /********************************/
-    /* 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;
+
+      /********************************/
+      /* 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                                     &&
+    if ( SUBPIXEL_HINTING_INFINALITY                                     &&
          exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
     {
 
@@ -7192,7 +7390,7 @@
       }
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = K;
   }
@@ -7274,7 +7472,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 */
                   {
@@ -7285,12 +7483,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 /* 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 /* 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;
@@ -7383,9 +7596,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++ )
         {
@@ -7414,7 +7627,7 @@
         }
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* SUBPIXEL_HINTING_INFINALITY */
 
       {
         FT_Long*  args   = exc->stack + exc->args;
-- 
2.5.5

>From e9a3cead3d96bef9f15724a56056a5ae646714ce Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Sun, 1 May 2016 19:00:10 +0200
Subject: [PATCH 3/3] Turn TT_LOADER_SET_PP macro into function, support
 subpixel hinting.

---
 src/truetype/ttgload.c | 89 +++++++++++++++++++++++++-------------------------
 1 file changed, 45 insertions(+), 44 deletions(-)

diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 517b5aa..4e8c0f1 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -1335,50 +1335,51 @@
    * (3) for everything else.
    *
    */
-   /* XXX merge infinality + lean datafields? */
+   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
+
 #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
+
+     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;
 
-#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 )
-
-#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#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 )
-
-#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+     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;
+   }
 
 
   /*************************************************************************/
@@ -1536,7 +1537,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 );
@@ -1611,7 +1612,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 );
-- 
2.5.5

_______________________________________________
Freetype-devel mailing list
Freetype-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to