freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft-devel] Experimental: v38 interpreter with minimal backwards comp


From: Werner LEMBERG
Subject: Re: [ft-devel] Experimental: v38 interpreter with minimal backwards compatibility mode and linear advance widths
Date: Mon, 25 Apr 2016 06:36:41 +0200 (CEST)

[CCing freetype-devel]

> Jep.  Werner wants to keep the infinality Code though since so many
> custom packages depend on it.  I hope that enough people jump ship
> that the code can be removed and left to the maintainers of those
> custom packages.

Both the original Infinality code and its lean version as written by
Nikolaus will stay together.  I plan to make the lean version the
default so that it gets a lot of testing.

Removal of the Infinality stuff won't happen in the next few years for
compatibility reasons.

Attached is what I currently have[1] – it's not yet ready, however.
Please use these patches for further tweaks.

  1. After some thinking I believe that having a new property
     `hinting-engine' is overkill that complicates the code
     unnecessarily.  Instead, what do you think about having a third
     value for `interpreter-version', namely

       TT_INTERPRETER_VERSION_40

     instead (or maybe version 39)?  IMHO, this classifies FreeType's
     `lean' interpreter capabilities better (actually, in hindsight,
     using version 38 for the Infinality code was a mistake which we
     can now correct).

     Note that I will extend ftview's `H' key to cycle through the
     versions, and having a single property to do that feels natural.

  2. In `ttinterp.c', please adjust and use the `SUBPIXEL_HINTING'
     macro, probably introducing `SUBPIXEL_HINTING_LEAN' and
     `SUBPIXEL_HINTING_INFINALITY' where necessary to simplify code
     that needs

       #if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
           defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
       ...
       #endif

     It's probably a good idea also to add another macro that makes
     the above a single #ifdef line instead, e.g.

       #ifdef OPTION_SUBPIXEL_HINTING
       ...
       #endif

  3. The last patch set is too big; I ask you to split it up into two
     or more patches.  It should probably first introduce the
     framework (i.e., defining the macros and the new code in
     ftdriver.c), then the actual changes.


       Werner


[1] For comparison with your original patches, I recommend that you
    check out FreeType twice so that you can apply both your original
    patches and my set.  Then use GNU wdiff to view the changed files.
    To get more readable output on the console, I use the following
    script to have color output, BTW.

      wdiff -n \
            -w $'\033[31;40m' \
            -x $'\033[0m' \
            -y $'\033[32;40m' \
            -z $'\033[0m' \
            $@
2016-04-24  Nikolaus Waxweiler  <address@hidden>

        [truetype] New implementation of v38 bytecode interpreter [1/x].

        This patch prepares data structures and the like.

        Note that currently this code compiles only if
        `TT_CONFIG_OPTION_SUBPIXEL_HINTING' isn't set.

        See added comments in `ttinterp.h' for more information on this and
        the following commit.

        * src/truetype/ttinterp.h (TT_ExecContextRec): Define fields
        `subpixel_hinting' and `vertical_lcd' unconditionally.
        New fields `iupx_called', iupy_called', and `grayscale_cleartype'.

        * src/truetype/ttdriver.c (tt_property_set): Handle v35 and v38
        interpreters unconditionally.

        * src/truetype/ttgload.c (TT_Hint_Glyph): Save phantom points unless
        in v38 backwards compatibility mode.
        (compute_glyph_metrics): Add v38 backwards compatibility mode
        constraint for adjusting advance widths.
        (tt_loader_init): Handle new flags `subpixel_hinting' and
        `grayscale_cleartype'.

        * src/truetype/ttobjs.c (tt_driver_init): Unconditionally set
        interpreter version number to 38.


diff --git a/devel/ftoption.h b/devel/ftoption.h
index b354efd..21daf41 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -602,7 +602,7 @@ FT_BEGIN_HEADER
   /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
   /*   defined.                                                            */
   /*                                                                       */
-#define TT_CONFIG_OPTION_SUBPIXEL_HINTING
+/*#define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 
   /*************************************************************************/
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index bbebabd..a856fed 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -72,11 +72,10 @@
       FT_UInt*  interpreter_version = (FT_UInt*)value;
 
 
-#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
+      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 &&
+           *interpreter_version != TT_INTERPRETER_VERSION_38 )
         error = FT_ERR( Unimplemented_Feature );
       else
-#endif
         driver->interpreter_version = *interpreter_version;
 
       return error;
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index c4038ee..31ad293 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -816,11 +816,16 @@
 
 #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];
+    /* Save possibly modified glyph phantom points unless in v38 backwards */
+    /* compatibility mode, where no movement on the x axis means no reason */
+    /* to change bearings or advance widths.                               */
+    if ( !loader->exec->backwards_compatibility )
+    {
+      loader->pp1 = zone->cur[zone->n_points - 4];
+      loader->pp2 = zone->cur[zone->n_points - 3];
+      loader->pp3 = zone->cur[zone->n_points - 2];
+      loader->pp4 = zone->cur[zone->n_points - 1];
+    }
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -1973,11 +1978,14 @@
     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 v38 interpreter is active.  See `ttinterp.h' for     */
+    /* details on backwards compatibility mode.                         */
+    if ( !( loader->exec && loader->exec->backwards_compatibility ) &&
+         !face->postscript.isFixedPitch                             &&
+         IS_HINTED( loader->load_flags )                            &&
+         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )          )
     {
       FT_Byte*  widthp;
 
@@ -2190,6 +2198,7 @@
 
     TT_Face    face;
     FT_Stream  stream;
+    TT_Driver  driver;
 #ifdef TT_USE_BYTECODE_INTERPRETER
     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
 #endif
@@ -2197,6 +2206,7 @@
 
     face   = (TT_Face)glyph->face;
     stream = face->root.stream;
+    driver = (TT_Driver)FT_FACE_DRIVER( face );
 
     FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
 
@@ -2207,6 +2217,8 @@
     {
       TT_ExecContext  exec;
       FT_Bool         grayscale;
+      FT_Bool         subpixel_hinting;
+      FT_Bool         grayscale_cleartype;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
@@ -2243,6 +2255,20 @@
       if ( !exec )
         return FT_THROW( Could_Not_Find_Context );
 
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      {
+        subpixel_hinting    = TRUE;
+        grayscale_cleartype = !FT_BOOL( load_flags & FT_LOAD_TARGET_LCD   ||
+                                        load_flags & FT_LOAD_TARGET_LCD_V );
+        exec->vertical_lcd  = FT_BOOL( load_flags & FT_LOAD_TARGET_LCD_V );
+      }
+      else
+      {
+        subpixel_hinting    = FALSE;
+        grayscale_cleartype = FALSE;
+        exec->vertical_lcd  = FALSE;
+      }
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -2303,8 +2329,9 @@
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
       {
-        grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
-                             FT_RENDER_MODE_MONO );
+        grayscale = FT_BOOL( !subpixel_hinting                 &&
+                             FT_LOAD_TARGET_MODE( load_flags )
+                               != FT_RENDER_MODE_MONO          );
       }
 
       error = TT_Load_Context( exec, face, size );
@@ -2342,6 +2369,28 @@
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
       {
+        /* a change from mono to subpixel rendering (and vice versa) */
+        /* requires a re-execution of the CVT program                */
+        if ( subpixel_hinting != exec->subpixel_hinting )
+        {
+          FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+                      " re-executing `prep' table\n" ));
+
+          exec->subpixel_hinting = subpixel_hinting;
+          reexecute              = TRUE;
+        }
+
+        /* a change from 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;
+        }
+
         /* a change from mono to grayscale rendering (and vice versa) */
         /* requires a re-execution of the CVT program                 */
         if ( grayscale != exec->grayscale )
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index e5a02b9..6bee188 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -247,7 +247,138 @@ 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? */
+    FT_Bool            grayscale;      /* bi-level hinting and */
+                                       /* grayscale rendering  */
+
+    /*
+     * 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).
+     *
+     * FreeType employs a small list of font-agnostic hacks to bludgeon
+     * non-native-ClearType fonts (except tricky ones[1]) into submission.
+     * FreeType 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 are 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, 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
+     *
+     * - All rounding instructions are turned into `Round_None' if the
+     *   freedom vector is parallel to the x axis (cf. `Round_*').  Given
+     *   ClearType's virtual increase of resolution on the x axis,
+     *   rounding to the physical pixel grid there doesn't make much
+     *   sense.  Native ClearType fonts know this, the rest (where
+     *   backwards compatibility applies) may or may not.
+     *
+     * - SHP denies movement on the x axis (cf. `Ins_SHP').  Prevents
+     *   dents.
+     *
+     * - 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.
+     *
+     * - MSIRP, MIAP, MDRP, and MIRP see a control value cut-in and
+     *   minimum distance of 0 if the freedom vector is parallel to the
+     *   x axis (cf. `Ins_MSIRP', `Ins_MIAP', `Ins_MDRP', and `Ins_MIRP').
+     *   See [2] for details.
+     *
+     * (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 v38
+     * 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 (v38 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.
+     *
+     */
+
+    FT_Bool            subpixel_hinting; /* using v38 implies this    */
+    FT_Bool            vertical_lcd;     /* long side of LCD subpixel */
+                                         /* rectangles is horizontal  */
+
+    /* Defaults to true with v38 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;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index a05f216..953931f 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1286,12 +1286,7 @@
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
     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;
-#endif
 
 #else /* !TT_USE_BYTECODE_INTERPRETER */
 
-- 
2.6.6

2016-04-24  Nikolaus Waxweiler  <address@hidden>
 
        [truetype] New implementation of v38 bytecode interpreter [2/x].

        This patch actually modifies the bytecode interpreter.

        Note that currently this code compiles only if
        `TT_CONFIG_OPTION_SUBPIXEL_HINTING' isn't set.

        See added comments in `ttinterp.h' for more information on this and
        the previous commit.

        * src/truetype/ttinterp.c (Direct_Move, Direct_Move_X,
        Direct_Move_Y): Handle backwards compatibility.
        (Round_To_Grid, Round_To_Half_Grid, Round_Down_To_Grid,
        Round_Up_To_Grid, Round_To_Double_Grid, Round_Super,
        Round_Super_45): Ditto.
        (Ins_FLIPPT, Ins_FLIPRGON, Ins_FLIPRGOFF): Ditto.
        (Move_Zp2_Point): Ditto.
        (Ins_SHP, Ins_SHPIX): Ditto.
        (Ins_MSIRP, Ins_MIAP, Ins_MDRP, Ins_MIRP): Ditto.
        (Ins_IUP, Ins_DELTAP): Ditto.
        (Ins_INSTCTRL): Handle native ClearType mode flag.
        (Ins_GETINFO): Handle v38 flags.
        (TT_RunIns): Handle backwards compatibility mode.

diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 78c35f2..5174002 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -1642,6 +1642,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,
@@ -1660,6 +1664,11 @@
            ( !exc->ignore_x_mode                                ||
              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      /* 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 ( !exc->backwards_compatibility )
         zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -1669,7 +1678,10 @@
 
     if ( v != 0 )
     {
-      zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+      if ( !( exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+        zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -1720,6 +1732,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.       */
   /*                                                                       */
   /*************************************************************************/
 
@@ -1736,6 +1749,8 @@
     if ( !SUBPIXEL_HINTING   ||
          !exc->ignore_x_mode )
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+    if ( !exc->backwards_compatibility )
       zone->cur[point].x += distance;
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
@@ -1750,8 +1765,11 @@
   {
     FT_UNUSED( exc );
 
-    zone->cur[point].y += distance;
-    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
+    if ( !( exc->backwards_compatibility         &&
+            exc->iupx_called && exc->iupy_called ) )
+      zone->cur[point].y += distance;
+
+    zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   }
 
 
@@ -1853,6 +1871,9 @@
   /* <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,
@@ -1860,8 +1881,9 @@
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED( exc );
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
 
     if ( distance >= 0 )
     {
@@ -1896,6 +1918,9 @@
   /* <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,
@@ -1903,8 +1928,9 @@
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED( exc );
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
 
     if ( distance >= 0 )
     {
@@ -1939,6 +1965,9 @@
   /* <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,
@@ -1946,8 +1975,9 @@
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED( exc );
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
 
     if ( distance >= 0 )
     {
@@ -1982,6 +2012,9 @@
   /* <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,
@@ -1989,8 +2022,9 @@
   {
     FT_F26Dot6  val;
 
-    FT_UNUSED( exc );
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
 
     if ( distance >= 0 )
     {
@@ -2025,6 +2059,9 @@
   /* <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,
@@ -2032,8 +2069,9 @@
   {
     FT_F26Dot6 val;
 
-    FT_UNUSED( exc );
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
 
     if ( distance >= 0 )
     {
@@ -2074,6 +2112,8 @@
   /*    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,
@@ -2082,6 +2122,9 @@
     FT_F26Dot6  val;
 
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
+
     if ( distance >= 0 )
     {
       val = ( distance - exc->phase + exc->threshold + compensation ) &
@@ -2123,6 +2166,8 @@
   /*    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,
@@ -2131,6 +2176,9 @@
     FT_F26Dot6  val;
 
 
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      return Round_None( exc, distance, compensation );
+
     if ( distance >= 0 )
     {
       val = ( ( distance - exc->phase + exc->threshold + compensation ) /
@@ -5049,6 +5097,12 @@
     if ( K == 3 )
       exc->ignore_x_mode = FT_BOOL( L == 4 );
 #endif
+
+    /* 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 ( K == 3 )
+      exc->backwards_compatibility = !FT_BOOL( L == 4 );
   }
 
 
@@ -5133,6 +5187,12 @@
     FT_UShort  point;
 
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      goto Fail;
+
     if ( exc->top < exc->GS.loop )
     {
       if ( exc->pedantic_hinting )
@@ -5179,6 +5239,12 @@
     FT_UShort  I, K, L;
 
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
@@ -5208,6 +5274,12 @@
     FT_UShort  I, K, L;
 
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
@@ -5267,6 +5339,7 @@
   }
 
 
+  /* See `ttinterp.h' for details on backwards compatibility mode. */
   static void
   Move_Zp2_Point( TT_ExecContext  exc,
                   FT_UShort       point,
@@ -5276,14 +5349,20 @@
   {
     if ( exc->GS.freeVector.x != 0 )
     {
-      exc->zp2.cur[point].x += dx;
+      if ( !( exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+        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;
+      if ( !( exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+        exc->zp2.cur[point].y += dy;
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -5337,7 +5416,10 @@
         Move_Zp2_Point( exc, point, 0, dy, TRUE );
       else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        Move_Zp2_Point( exc, point, dx, dy, TRUE );
+        if ( exc->backwards_compatibility )
+          Move_Zp2_Point( exc, point, 0, dy, TRUE );
+        else
+          Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
       exc->GS.loop--;
     }
@@ -5574,7 +5656,17 @@
 
 #else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
-      Move_Zp2_Point( exc, point, dx, dy, TRUE );
+      if ( 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
+        Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
 #endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
@@ -5616,6 +5708,13 @@
 
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    FT_F26Dot6  control_value_cutin = exc->GS.control_value_cutin;
+
+
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      control_value_cutin = 0;
+
     point = (FT_UShort)args[0];
 
     if ( BOUNDS( point,       exc->zp1.n_points ) ||
@@ -5646,6 +5745,10 @@
       distance = args[1];
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    if ( exc->backwards_compatibility                        &&
+         FT_ABS( distance - args[1] ) >= control_value_cutin )
+      distance = args[1];
+
     exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
     exc->GS.rp1 = exc->GS.rp0;
@@ -5738,6 +5841,10 @@
       control_value_cutin = 0;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+      control_value_cutin = 0;
+
     if ( BOUNDS( point,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
     {
@@ -5845,6 +5952,10 @@
       minimum_distance = 0;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+      minimum_distance = 0;
+
     point = (FT_UShort)args[0];
 
     if ( BOUNDS( point,       exc->zp1.n_points ) ||
@@ -5998,6 +6109,10 @@
       control_value_cutin = minimum_distance = 0;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+      control_value_cutin = minimum_distance = 0;
+
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
     if ( BOUNDS( point,       exc->zp1.n_points ) ||
@@ -6106,6 +6221,13 @@
       }
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+      if ( exc->backwards_compatibility &&
+           exc->GS.gep0 == exc->GS.gep1 )
+      {
+        if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+          cvt_dist = org_dist;
+      }
+
       distance = Round_None(
                    exc,
                    cvt_dist,
@@ -6324,6 +6446,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 +6454,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 +6843,20 @@
     FT_Short  contour;       /* current contour */
 
 
+    /* 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 ( exc->backwards_compatibility )
+    {
+      if ( exc->iupx_called && exc->iupy_called )
+        return;
+
+      if ( exc->opcode & 1 )
+        exc->iupx_called = TRUE;
+      else
+        exc->iupy_called = TRUE;
+    }
+
     /* ignore empty outlines */
     if ( exc->pts.n_contours == 0 )
       return;
@@ -6946,7 +7084,17 @@
           else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
-            exc->func_move( exc, &exc->zp0, A, B );
+            /* See `ttinterp.h' for details on backwards compatibility */
+            /* mode.                                                   */
+            if ( 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
+              exc->func_move( exc, &exc->zp0, A, B );
         }
       }
       else
@@ -7063,10 +7211,13 @@
                FT_Long*        args )
   {
     FT_Long  K;
+    TT_Driver driver;
 
 
     K = 0;
 
+    driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     /********************************/
     /* RASTERIZER VERSION           */
@@ -7091,7 +7242,7 @@
     else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
       if ( ( args[0] & 1 ) != 0 )
-        K = TT_INTERPRETER_VERSION_35;
+        K = driver->interpreter_version;
 
     /********************************/
     /* GLYPH ROTATED                */
@@ -7110,13 +7261,64 @@
       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;
 
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    {
+      /********************************/
+      /* HINTING FOR SUBPIXEL         */
+      /* Selector Bit:  6             */
+      /* Return Bit(s): 13            */
+      /*                              */
+      /* v38 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 )
+        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;
+    }
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
     if ( SUBPIXEL_HINTING                                     &&
@@ -7274,6 +7476,8 @@
     FT_Long    ins_counter = 0;  /* executed instructions counter */
     FT_UShort  i;
 
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     FT_Byte    opcode_pattern[1][2] = {
                   /* #8 TypeMan Talk Align */
@@ -7292,6 +7496,19 @@
     exc->iup_called = FALSE;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+    /* 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 ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+         !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;
+
     /* set PPEM and CVT functions */
     exc->tt_metrics.ratio = 0;
     if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
-- 
2.6.6

diff --git a/devel/ftoption.h b/devel/ftoption.h
index 21daf41..27891fb 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -585,24 +585,53 @@ 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:                                          */
-  /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
-  /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
-  /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
-  /*                                                                       */
-/*#define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING or                           */
+  /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN 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 two options.                                                */
+  /*                                                                       */
+  /* - TT_CONFIG_OPTION_SUBPIXEL_HINTING: This 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.                                                             */
+  /*                                                                       */
+  /* - TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN: 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.                                */
+  /*                                                                       */
+  /* 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, you can switch between between v35  */
+  /* and the ones you define.                                              */
+  /*                                                                       */
+  /* 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_LEAN
 
 
   /*************************************************************************/
diff --git a/include/freetype/config/ftoption.h 
b/include/freetype/config/ftoption.h
index a8097fe..dfab753 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -585,24 +585,53 @@ 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:                                          */
-  /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
-  /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
-  /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING or                           */
+  /* TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN 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 two options.                                                */
+  /*                                                                       */
+  /* - TT_CONFIG_OPTION_SUBPIXEL_HINTING: This 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.                                                             */
+  /*                                                                       */
+  /* - TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN: 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.                                */
+  /*                                                                       */
+  /* 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, you can switch between between v35  */
+  /* and the ones you define.                                              */
+  /*                                                                       */
+  /* 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_LEAN
 
 
   /*************************************************************************/
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..978d81a 100644
--- a/include/freetype/ftttdrv.h
+++ b/include/freetype/ftttdrv.h
@@ -139,9 +139,9 @@ FT_BEGIN_HEADER
    *
    * @description:
    *   Currently, two versions are available, representing the bytecode
-   *   interpreter with and without subpixel hinting support,
-   *   respectively.  The default is subpixel support if
-   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel
+   *   interpreter with and without subpixel hinting support, respectively.
+   *   The default is subpixel support if TT_CONFIG_OPTION_SUBPIXEL_HINTING
+   *   or TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN is defined, and no subpixel
    *   support otherwise (since it isn't available then).
    *
    *   If subpixel hinting is on, many TrueType bytecode instructions behave
@@ -150,7 +150,7 @@ FT_BEGIN_HEADER
    *   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.
    *
    *   Details on subpixel hinting and some of the necessary tweaks can be
    *   found in Greg Hitchcock's whitepaper at
@@ -180,6 +180,61 @@ FT_BEGIN_HEADER
 
   /**************************************************************************
    *
+   * @property:
+   *   hinting-engine[tt]
+   *
+   * @description:
+   *   This property allows switching between the older Infinality
+   *   interpreter for subpixel hinting if TT_CONFIG_OPTION_SUBPIXEL_HINTING
+   *   is defined and the stripped-down lean version of it if
+   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN is defined.  Lean is the
+   *   default.
+   *
+   *   The following example code demonstrates how to select Infinality's
+   *   hinting engine (omitting the error handling).
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_UInt     hinting_engine = FT_TT_HINTING_INFINALITY;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "truetype",
+   *                               "hinting-engine",
+   *                               &hinting_engine );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_TT_HINTING_XXX
+   *
+   * @description:
+   *   A list of constants used for the @hinting-engine[tt] property to
+   *   select the v38 (ClearType) hinting engine for TrueType fonts.
+   *
+   * @values:
+   *   FT_TT_HINTING_INFINALITY ::
+   *     The older Infinality hinting engine.  Configurable but slow.
+   *
+   *   FT_TT_HINTING_LEAN ::
+   *     The newer hinting engine contributed by Nikolaus Waxweiler.  Not
+   *     configurable but fast.
+   *
+   */
+#define FT_TT_HINTING_INFINALITY  0
+#define FT_TT_HINTING_LEAN        1
+
+
+  /**************************************************************************
+   *
    * @enum:
    *   TT_INTERPRETER_VERSION_XXX
    *
@@ -296,7 +351,10 @@ FT_BEGIN_HEADER
    *
    */
 #define TT_INTERPRETER_VERSION_35  35
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
 #define TT_INTERPRETER_VERSION_38  38
+#endif
 
  /* */
 
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index a856fed..f9eb311 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -72,14 +72,32 @@
       FT_UInt*  interpreter_version = (FT_UInt*)value;
 
 
-      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 &&
-           *interpreter_version != TT_INTERPRETER_VERSION_38 )
+      if ( *interpreter_version != TT_INTERPRETER_VERSION_35
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+           && *interpreter_version != TT_INTERPRETER_VERSION_38
+#endif
+          )
         error = FT_ERR( Unimplemented_Feature );
       else
         driver->interpreter_version = *interpreter_version;
 
       return error;
     }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    {
+      FT_UInt*  hinting_engine = (FT_UInt*)value;
+
+
+#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( *hinting_engine != FT_TT_HINTING_LEAN )
+        error = FT_ERR( Unimplemented_Feature );
+      else
+#endif
+        driver->hinting_engine = *hinting_engine;
+
+      return error;
+    }
 
     FT_TRACE0(( "tt_property_set: missing property `%s'\n",
                 property_name ));
@@ -107,6 +125,17 @@
 
       return error;
     }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    {
+      FT_UInt   hinting_engine = driver->hinting_engine;
+      FT_UInt*  val            = (FT_UInt*)value;
+
+
+      *val = hinting_engine;
+
+      return error;
+    }
+
 
     FT_TRACE0(( "tt_property_get: missing property `%s'\n",
                 property_name ));
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 31ad293..3e6f77c 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -154,7 +154,8 @@
     loader->vadvance     = advance_height;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+    if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY  &&
+         driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
          loader->exec                                             )
     {
       loader->exec->sph_tweak_flags = 0;
@@ -733,7 +734,8 @@
   TT_Hint_Glyph( TT_Loader  loader,
                  FT_Bool    is_composite )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     TT_Face    face   = loader->face;
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
@@ -816,19 +818,25 @@
 
 #endif
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* Save possibly modified glyph phantom points unless in v38 backwards */
     /* compatibility mode, where no movement on the x axis means no reason */
     /* to change bearings or advance widths.                               */
-    if ( !loader->exec->backwards_compatibility )
+    if ( !( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+            !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_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     }
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY  &&
+         driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
     {
       if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
         FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
@@ -923,7 +931,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY  &&
+           driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
         /* scale, but only if enabled and only if TT hinting is being used */
         if ( IS_HINTED( loader->load_flags ) )
@@ -1083,7 +1092,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;
@@ -1329,6 +1338,7 @@
    * (3) for everything else.
    *
    */
+   /* XXX merge infinality + lean datafields? */
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
 #define TT_LOADER_SET_PP( loader )                                          \
@@ -1951,7 +1961,8 @@
                          FT_UInt    glyph_index )
   {
     TT_Face    face   = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
@@ -1982,10 +1993,14 @@
     /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */
     /* mode of the v38 interpreter is active.  See `ttinterp.h' for     */
     /* details on backwards compatibility mode.                         */
-    if ( !( loader->exec && loader->exec->backwards_compatibility ) &&
-         !face->postscript.isFixedPitch                             &&
-         IS_HINTED( loader->load_flags )                            &&
-         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )          )
+    if (
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+         !( driver->hinting_engine == FT_TT_HINTING_LEAN              &&
+            ( 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;
 
@@ -1996,7 +2011,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY   &&
+           driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
         FT_Bool  ignore_x_mode;
 
@@ -2198,15 +2214,17 @@
 
     TT_Face    face;
     FT_Stream  stream;
-    TT_Driver  driver;
 #ifdef TT_USE_BYTECODE_INTERPRETER
     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
 #endif
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
+#endif
 
 
     face   = (TT_Face)glyph->face;
     stream = face->root.stream;
-    driver = (TT_Driver)FT_FACE_DRIVER( face );
 
     FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
 
@@ -2216,13 +2234,13 @@
     if ( IS_HINTED( load_flags ) && !glyf_table_only )
     {
       TT_ExecContext  exec;
-      FT_Bool         grayscale;
-      FT_Bool         subpixel_hinting;
+      FT_Bool         grayscale = TRUE;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+      FT_Bool         subpixel_hinting_lean;
       FT_Bool         grayscale_cleartype;
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
-
       FT_Bool  subpixel_hinting = FALSE;
 
 #if 0
@@ -2255,23 +2273,30 @@
       if ( !exec )
         return FT_THROW( Could_Not_Find_Context );
 
-      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+      if ( driver->hinting_engine      == FT_TT_HINTING_LEAN        &&
+           driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
-        subpixel_hinting    = TRUE;
-        grayscale_cleartype = !FT_BOOL( load_flags & FT_LOAD_TARGET_LCD   ||
-                                        load_flags & FT_LOAD_TARGET_LCD_V );
-        exec->vertical_lcd  = FT_BOOL( load_flags & FT_LOAD_TARGET_LCD_V );
+        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    = FALSE;
-        grayscale_cleartype = FALSE;
-        exec->vertical_lcd  = FALSE;
+        subpixel_hinting_lean   = FALSE;
+        grayscale_cleartype     = FALSE;
+        exec->vertical_lcd_lean = FALSE;
       }
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY  &&
+           driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
         subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
                                       FT_RENDER_MODE_MONO               )  &&
@@ -2329,9 +2354,20 @@
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
       {
-        grayscale = FT_BOOL( !subpixel_hinting                 &&
-                             FT_LOAD_TARGET_MODE( load_flags )
-                               != FT_RENDER_MODE_MONO          );
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+        if ( driver->hinting_engine == FT_TT_HINTING_LEAN )
+          grayscale = FT_BOOL( !subpixel_hinting_lean               &&
+                               FT_LOAD_TARGET_MODE( load_flags ) !=
+                                 FT_RENDER_MODE_MONO                );
+        else
+          grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                                 FT_RENDER_MODE_MONO             );
+#else
+        grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                               FT_RENDER_MODE_MONO             );
+#endif
+
       }
 
       error = TT_Load_Context( exec, face, size );
@@ -2340,7 +2376,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      if ( driver->hinting_engine      == FT_TT_HINTING_INFINALITY  &&
+           driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
         /* a change from mono to subpixel rendering (and vice versa) */
         /* requires a re-execution of the CVT program                */
@@ -2369,27 +2406,33 @@
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
       {
-        /* a change from mono to subpixel rendering (and vice versa) */
-        /* requires a re-execution of the CVT program                */
-        if ( subpixel_hinting != exec->subpixel_hinting )
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+        if ( driver->hinting_engine == FT_TT_HINTING_LEAN )
         {
-          FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
-                      " re-executing `prep' table\n" ));
+          /* 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 = subpixel_hinting;
-          reexecute              = TRUE;
-        }
+            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" ));
+          /* 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;
+            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                 */
@@ -2426,7 +2469,8 @@
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       /* 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->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           exec->GS.instruct_control & 4                      )
         exec->ignore_x_mode = 0;
 #endif
 
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 5174002..402136c 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -286,8 +286,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;
@@ -1653,23 +1653,39 @@
                FT_F26Dot6      distance )
   {
     FT_F26Dot6  v;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     v = exc->GS.freeVector.x;
 
     if ( v != 0 )
     {
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( !SUBPIXEL_HINTING                                      ||
-           ( !exc->ignore_x_mode                                ||
-             ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY         &&
+           ( !SUBPIXEL_HINTING                                      ||
+             ( !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 );
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
       /* 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 ( !exc->backwards_compatibility )
+      if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+           !exc->backwards_compatibility                )
         zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+#endif
+
+#else /* no subpixel hinting */
+      zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+#endif
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
@@ -1678,9 +1694,12 @@
 
     if ( v != 0 )
     {
-      if ( !( exc->backwards_compatibility &&
-              exc->iupx_called             &&
-              exc->iupy_called             ) )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+      if ( !( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+              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;
@@ -1743,15 +1762,33 @@
                  FT_UShort       point,
                  FT_F26Dot6      distance )
   {
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#else
     FT_UNUSED( exc );
+#endif
+
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( !SUBPIXEL_HINTING   ||
-         !exc->ignore_x_mode )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         ( !SUBPIXEL_HINTING   ||
+           !exc->ignore_x_mode )                            )
+      zone->cur[point].x += distance;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
-    if ( !exc->backwards_compatibility )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         !exc->backwards_compatibility                )
       zone->cur[point].x += distance;
+#endif
+
+#else /* no subpixel hinting */
+    zone->cur[point].x += distance;
+#endif
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
   }
@@ -1765,8 +1802,10 @@
   {
     FT_UNUSED( exc );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     if ( !( exc->backwards_compatibility         &&
             exc->iupx_called && exc->iupy_called ) )
+#endif
       zone->cur[point].y += distance;
 
     zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
@@ -1880,10 +1919,16 @@
                  FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
 
     if ( distance >= 0 )
     {
@@ -1927,10 +1972,17 @@
                       FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -1974,10 +2026,17 @@
                       FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -2021,10 +2080,17 @@
                     FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -2067,11 +2133,18 @@
                         FT_F26Dot6      distance,
                         FT_F26Dot6      compensation )
   {
-    FT_F26Dot6 val;
-
+    FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -2120,10 +2193,17 @@
                FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -2174,10 +2254,17 @@
                   FT_F26Dot6      compensation )
   {
     FT_F26Dot6  val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
-
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       return Round_None( exc, distance, compensation );
+#else
+    FT_UNUSED( exc );
+#endif
+
 
     if ( distance >= 0 )
     {
@@ -2926,7 +3013,9 @@
   Ins_RS( TT_ExecContext  exc,
           FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
     FT_ULong  I = (FT_ULong)args[0];
 
@@ -2940,42 +3029,28 @@
     }
     else
     {
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       /* subpixel hinting - avoid Typeman Dstroke and */
       /* IStroke and Vacuform rounds                  */
-      if ( SUBPIXEL_HINTING                            &&
-           exc->ignore_x_mode                          &&
-           ( ( I == 24                             &&
-               ( exc->face->sph_found_func_flags &
-                 ( SPH_FDEF_SPACING_1 |
-                   SPH_FDEF_SPACING_2 )          ) ) ||
-             ( I == 22                      &&
-               ( exc->sph_in_func_flags   &
-                 SPH_FDEF_TYPEMAN_STROKES ) )        ||
-             ( I == 8                              &&
-               ( exc->face->sph_found_func_flags &
-                 SPH_FDEF_VACUFORM_ROUND_1       ) &&
-               exc->iup_called                     ) ) )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           ( SUBPIXEL_HINTING                          &&
+             exc->ignore_x_mode                        &&
+             ( ( I == 24                             &&
+                 ( exc->face->sph_found_func_flags &
+                   ( SPH_FDEF_SPACING_1 |
+                     SPH_FDEF_SPACING_2 )          ) ) ||
+               ( I == 22                      &&
+                 ( exc->sph_in_func_flags   &
+                   SPH_FDEF_TYPEMAN_STROKES ) )        ||
+               ( I == 8                              &&
+                 ( exc->face->sph_found_func_flags &
+                   SPH_FDEF_VACUFORM_ROUND_1       ) &&
+               exc->iup_called                     ) ) )      )
         args[0] = 0;
       else
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
         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 */
   }
 
 
@@ -3456,6 +3531,10 @@
     FT_ULong       n;
     TT_DefRecord*  rec;
     TT_DefRecord*  limit;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver      driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
+
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     /* arguments to opcodes are skipped by `SKIP_Code' */
@@ -3615,7 +3694,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( SUBPIXEL_HINTING )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
@@ -3801,6 +3881,9 @@
     FT_ULong       F;
     TT_CallRec*    pCrec;
     TT_DefRecord*  def;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver      driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     /* first of all, check the index */
@@ -3840,14 +3923,17 @@
       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 )        ) )
-      goto Fail;
-    else
-      exc->sph_in_func_flags = def->sph_fdef_flags;
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+    {
+      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 )        ) )
+        goto Fail;
+      else
+        exc->sph_in_func_flags = def->sph_fdef_flags;
+    }
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
     /* check the call stack */
@@ -3890,6 +3976,9 @@
     FT_ULong       F;
     TT_CallRec*    pCrec;
     TT_DefRecord*  def;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver      driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     /* first of all, check the index */
@@ -3928,12 +4017,15 @@
       goto Fail;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                    &&
-         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;
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+    {
+      if ( SUBPIXEL_HINTING                                    &&
+           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 */
 
     /* check stack */
@@ -4775,6 +4867,9 @@
   {
     FT_UShort   K, L;
     FT_F26Dot6  D;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     K = (FT_UShort)args[1];
@@ -4831,9 +4926,10 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
-    if ( SUBPIXEL_HINTING   &&
-         exc->ignore_x_mode &&
-         FT_ABS( D ) == 64  )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
+         exc->ignore_x_mode                                 &&
+         FT_ABS( D ) == 64                                  )
       D += 1;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
@@ -5059,7 +5155,11 @@
   Ins_INSTCTRL( TT_ExecContext  exc,
                 FT_Long*        args )
   {
-    FT_ULong  K, L, Kf;
+    FT_ULong   K, L, Kf;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     K = (FT_ULong)args[1];
@@ -5091,18 +5191,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_CONFIG_OPTION_SUBPIXEL_HINTING
+      /* INSTCTRL modifying flag 3 also has an effect */
+      /* outside of the CVT program                   */
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+        exc->ignore_x_mode = FT_BOOL( L == 4 );
 #endif
 
-    /* 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 ( K == 3 )
-      exc->backwards_compatibility = !FT_BOOL( L == 4 );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+      /* 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 ( driver->hinting_engine == FT_TT_HINTING_LEAN )
+        exc->backwards_compatibility = ! FT_BOOL( L == 4 );
+#endif
+    }
   }
 
 
@@ -5187,11 +5292,13 @@
     FT_UShort  point;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
     if ( exc->backwards_compatibility &&
          exc->iupx_called             &&
          exc->iupy_called             )
       goto Fail;
+#endif
 
     if ( exc->top < exc->GS.loop )
     {
@@ -5239,11 +5346,13 @@
     FT_UShort  I, K, L;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
     if ( exc->backwards_compatibility &&
          exc->iupx_called             &&
          exc->iupy_called             )
       return;
+#endif
 
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
@@ -5274,11 +5383,13 @@
     FT_UShort  I, K, L;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
     if ( exc->backwards_compatibility &&
          exc->iupx_called             &&
          exc->iupy_called             )
       return;
+#endif
 
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
@@ -5349,20 +5460,26 @@
   {
     if ( exc->GS.freeVector.x != 0 )
     {
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
       if ( !( exc->backwards_compatibility &&
               exc->iupx_called             &&
               exc->iupy_called             ) )
+#endif
         exc->zp2.cur[point].x += dx;
+
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
 
     if ( exc->GS.freeVector.y != 0 )
     {
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
       if ( !( 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;
     }
@@ -5383,6 +5500,10 @@
 
     FT_F26Dot6       dx, dy;
     FT_UShort        point;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver        driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     if ( exc->top < exc->GS.loop )
@@ -5411,14 +5532,18 @@
       else
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       /* doesn't follow Cleartype spec but produces better result */
-      if ( SUBPIXEL_HINTING   &&
-           exc->ignore_x_mode )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           ( SUBPIXEL_HINTING   &&
+             exc->ignore_x_mode )                             )
         Move_Zp2_Point( exc, point, 0, dy, TRUE );
       else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        if ( exc->backwards_compatibility )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+        if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+             exc->backwards_compatibility                 )
           Move_Zp2_Point( exc, point, 0, dy, TRUE );
         else
+#endif
           Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
       exc->GS.loop--;
@@ -5549,6 +5674,10 @@
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     FT_Int      B1, B2;
 #endif
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     if ( exc->top < exc->GS.loop + 1 )
@@ -5577,6 +5706,7 @@
       }
       else
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
       {
         /*  If not using ignore_x_mode rendering, allow ZP2 move.        */
         /*  If inline deltas aren't allowed, skip ZP2 move.              */
@@ -5651,12 +5781,11 @@
         else
           Move_Zp2_Point( exc, point, dx, dy, TRUE );
       }
-
-    Skip:
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-      if ( exc->backwards_compatibility )
+      else
+#endif
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+      if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+           exc->backwards_compatibility                 )
       {
         /* XXX: breaks Rokkitt < v1.2                   */
         /*      (glyphs explode vertically on ALIGNRP). */
@@ -5666,10 +5795,12 @@
           Move_Zp2_Point( exc, point, 0, dy, TRUE );
       }
       else
-        Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
 #endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+        Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    Skip:
+#endif
       exc->GS.loop--;
     }
 
@@ -5691,12 +5822,18 @@
   {
     FT_UShort   point;
     FT_F26Dot6  distance;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    FT_F26Dot6  control_value_cutin = 0; /* pacify compiler */
+    FT_F26Dot6  control_value_cutin = 0;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#else
+    FT_UNUSED( control_value_cutin );
+#endif
 
 
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   )
     {
       control_value_cutin = exc->GS.control_value_cutin;
 
@@ -5705,15 +5842,17 @@
            !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
         control_value_cutin = 0;
     }
-
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
-    FT_F26Dot6  control_value_cutin = exc->GS.control_value_cutin;
-
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       control_value_cutin = 0;
+    else
+#endif
+      control_value_cutin = exc->GS.control_value_cutin;
 
     point = (FT_UShort)args[0];
 
@@ -5738,16 +5877,20 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     /* subpixel hinting - make MSIRP respect CVT cut-in; */
-    if ( SUBPIXEL_HINTING                                    &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY  &&
+         SUBPIXEL_HINTING                                    &&
          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 */
 
-    if ( exc->backwards_compatibility                        &&
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN        &&
+         exc->backwards_compatibility                        &&
          FT_ABS( distance - args[1] ) >= control_value_cutin )
       distance = args[1];
+#endif
 
     exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
@@ -5772,6 +5915,9 @@
     FT_UShort   point;
     FT_F26Dot6  cur_dist;
     FT_F26Dot6  distance;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     point = (FT_UShort)args[0];
@@ -5787,9 +5933,10 @@
     {
       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 )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   &&
+           exc->ignore_x_mode                                 &&
+           exc->GS.freeVector.x != 0                          )
         distance = Round_None(
                      exc,
                      cur_dist,
@@ -5826,6 +5973,10 @@
     FT_F26Dot6  distance;
     FT_F26Dot6  org_dist;
     FT_F26Dot6  control_value_cutin;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     control_value_cutin = exc->GS.control_value_cutin;
@@ -5833,7 +5984,8 @@
     point               = (FT_UShort)args[0];
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
          exc->ignore_x_mode                                 &&
          exc->GS.freeVector.x != 0                          &&
          exc->GS.freeVector.y == 0                          &&
@@ -5841,9 +5993,13 @@
       control_value_cutin = 0;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       control_value_cutin = 0;
+#endif
 
     if ( BOUNDS( point,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
@@ -5880,9 +6036,10 @@
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
       /* Determined via experimentation and may be incorrect...         */
-      if ( !SUBPIXEL_HINTING                      ||
-           ( !exc->ignore_x_mode                ||
-             !exc->face->sph_compatibility_mode ) )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           ( !SUBPIXEL_HINTING                      ||
+             ( !exc->ignore_x_mode                ||
+               !exc->face->sph_compatibility_mode ) )         )
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
         exc->zp0.org[point].x = TT_MulFix14( distance,
                                              exc->GS.freeVector.x );
@@ -5891,11 +6048,12 @@
       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                      )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
+         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 */
 
@@ -5907,9 +6065,10 @@
         distance = org_dist;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   &&
+           exc->ignore_x_mode                                 &&
+           exc->GS.freeVector.x != 0                          )
         distance = Round_None( exc,
                                distance,
                                exc->tt_metrics.compensations[0] );
@@ -5938,23 +6097,32 @@
   Ins_MDRP( TT_ExecContext  exc,
             FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  org_dist, distance, minimum_distance;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     minimum_distance = exc->GS.minimum_distance;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
          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 */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0x0                  )
       minimum_distance = 0;
+#endif
 
     point = (FT_UShort)args[0];
 
@@ -6019,9 +6187,10 @@
     if ( ( exc->opcode & 4 ) != 0 )
     {
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   &&
+           exc->ignore_x_mode                                 &&
+           exc->GS.freeVector.x != 0                          )
         distance = Round_None(
                      exc,
                      org_dist,
@@ -6094,6 +6263,10 @@
     FT_Int      B2           = 0;
     FT_Bool     reverse_move = FALSE;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 
     minimum_distance    = exc->GS.minimum_distance;
@@ -6102,16 +6275,22 @@
     cvtEntry            = (FT_ULong)( args[1] + 1 );
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
          exc->ignore_x_mode                                 &&
          exc->GS.freeVector.x != 0                          &&
          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       control_value_cutin = minimum_distance = 0;
+    else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* See `ttinterp.h' for details on backwards compatibility mode. */
-    if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 &&
+         exc->GS.freeVector.y == 0                    )
       control_value_cutin = minimum_distance = 0;
+#endif
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
@@ -6165,7 +6344,8 @@
     }
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY        &&
+         SUBPIXEL_HINTING                                          &&
          exc->ignore_x_mode                                        &&
          exc->GS.freeVector.y != 0                                 &&
          ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
@@ -6212,21 +6392,23 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
       /* do cvt cut-in always in MIRP for sph */
-      if ( SUBPIXEL_HINTING             &&
-           exc->ignore_x_mode           &&
-           exc->GS.gep0 == exc->GS.gep1 )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   &&
+           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 */
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
       if ( exc->backwards_compatibility &&
            exc->GS.gep0 == exc->GS.gep1 )
       {
         if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
           cvt_dist = org_dist;
       }
+#endif
 
       distance = Round_None(
                    exc,
@@ -6251,7 +6433,8 @@
     }
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   )
     {
       B1 = exc->zp1.cur[point].y;
 
@@ -6273,7 +6456,8 @@
     exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   )
     {
       B2 = exc->zp1.cur[point].y;
 
@@ -6320,10 +6504,13 @@
   {
     FT_UShort   point;
     FT_F26Dot6  distance;
-
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver   driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY        &&
+         SUBPIXEL_HINTING                                          &&
          exc->ignore_x_mode                                        &&
          exc->iup_called                                           &&
          ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
@@ -6842,11 +7029,18 @@
     FT_UInt   point;         /* current point   */
     FT_Short  contour;       /* current contour */
 
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* 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 ( exc->backwards_compatibility )
+    if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+         exc->backwards_compatibility                 )
     {
       if ( exc->iupx_called && exc->iupy_called )
         return;
@@ -6856,6 +7050,7 @@
       else
         exc->iupy_called = TRUE;
     }
+#endif
 
     /* ignore empty outlines */
     if ( exc->pts.n_contours == 0 )
@@ -6881,8 +7076,9 @@
     point   = 0;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING   &&
-         exc->ignore_x_mode )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
+         exc->ignore_x_mode                                 )
     {
       exc->iup_called = TRUE;
       if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
@@ -6960,11 +7156,16 @@
     FT_UShort  A;
     FT_ULong   C, P;
     FT_Long    B;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     FT_UShort  B1, B2;
 
 
-    if ( SUBPIXEL_HINTING                                         &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY       &&
+         SUBPIXEL_HINTING                                         &&
          exc->ignore_x_mode                                       &&
          exc->iup_called                                          &&
          ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
@@ -7025,7 +7226,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-          if ( SUBPIXEL_HINTING )
+          if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+               SUBPIXEL_HINTING                                   )
           {
             /*
              *  Allow delta move if
@@ -7084,9 +7286,13 @@
           else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+          {
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
             /* See `ttinterp.h' for details on backwards compatibility */
             /* mode.                                                   */
-            if ( exc->backwards_compatibility )
+            if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+                 exc->backwards_compatibility                 )
             {
               if ( !( exc->iupx_called && exc->iupy_called )              &&
                    ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
@@ -7094,7 +7300,9 @@
                 exc->func_move( exc, &exc->zp0, A, B );
             }
             else
+#endif
               exc->func_move( exc, &exc->zp0, A, B );
+          }
         }
       }
       else
@@ -7210,8 +7418,8 @@
   Ins_GETINFO( TT_ExecContext  exc,
                FT_Long*        args )
   {
-    FT_Long  K;
-    TT_Driver driver;
+    FT_Long    K;
+    TT_Driver  driver;
 
 
     K = 0;
@@ -7224,9 +7432,10 @@
     /* Selector Bit:  0             */
     /* Return Bit(s): 0-7           */
     /*                              */
-    if ( SUBPIXEL_HINTING      &&
-         ( args[0] & 1 ) != 0  &&
-         exc->subpixel_hinting )
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+         SUBPIXEL_HINTING                                   &&
+         ( args[0] & 1 ) != 0                               &&
+         exc->subpixel_hinting                              )
     {
       if ( exc->ignore_x_mode )
       {
@@ -7269,7 +7478,9 @@
     if ( ( args[0] & 32 ) != 0 && exc->grayscale )
       K |= 1 << 12;
 
-    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    if ( driver->hinting_engine      == FT_TT_HINTING_LEAN        &&
+         driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
     {
       /********************************/
       /* HINTING FOR SUBPIXEL         */
@@ -7285,7 +7496,7 @@
       /* Selector Bit:  8             */
       /* Return Bit(s): 15            */
       /*                              */
-      if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
+      if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
         K |= 1 << 15;
 
       /********************************/
@@ -7318,10 +7529,12 @@
       if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
         K |= 1 << 19;
     }
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-    if ( SUBPIXEL_HINTING                                     &&
+    if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY   &&
+         SUBPIXEL_HINTING                                     &&
          exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
     {
 
@@ -7476,7 +7689,10 @@
     FT_Long    ins_counter = 0;  /* executed instructions counter */
     FT_UShort  i;
 
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     FT_Byte    opcode_pattern[1][2] = {
@@ -7496,11 +7712,13 @@
     exc->iup_called = FALSE;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /* 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 ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+    if ( driver->hinting_engine      == FT_TT_HINTING_LEAN        &&
+         driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
          !FT_IS_TRICKY( &exc->face->root )                        )
       exc->backwards_compatibility = !( exc->GS.instruct_control & 4 );
     else
@@ -7508,6 +7726,7 @@
 
     exc->iupx_called = FALSE;
     exc->iupy_called = FALSE;
+#endif
 
     /* set PPEM and CVT functions */
     exc->tt_metrics.ratio = 0;
@@ -7602,7 +7821,8 @@
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
-      if ( SUBPIXEL_HINTING )
+      if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+           SUBPIXEL_HINTING                                   )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 6bee188..98a99c5 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -250,6 +250,7 @@ FT_BEGIN_HEADER
     FT_Bool            grayscale;      /* bi-level hinting and */
                                        /* grayscale rendering  */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     /*
      * Modern TrueType fonts are usually rendered through Microsoft's
      * collection of rendering techniques called ClearType (e.g., subpixel
@@ -359,12 +360,19 @@ FT_BEGIN_HEADER
      *
      */
 
-    FT_Bool            subpixel_hinting; /* using v38 implies this    */
-    FT_Bool            vertical_lcd;     /* long side of LCD subpixel */
-                                         /* rectangles is horizontal  */
+    /* Using v38 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;
 
-    /* Defaults to true with v38 interpreter.  If this is false, it   */
-    /* implies the interpreter is in v35 or in native ClearType mode. */
+    /* 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 v38 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 */
@@ -379,6 +387,7 @@ FT_BEGIN_HEADER
     /* 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_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN */
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 953931f..2b78060 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1286,7 +1286,20 @@
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
     TT_Driver  driver = (TT_Driver)ttdriver;
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING      || \
+    defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
+#else
+    driver->interpreter_version = TT_INTERPRETER_VERSION_35;
+#endif
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING       && \
+    !defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+    driver->hinting_engine = FT_TT_HINTING_INFINALITY;
+#else
+    driver->hinting_engine = FT_TT_HINTING_LEAN;
+#endif
 
 #else /* !TT_USE_BYTECODE_INTERPRETER */
 
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index ed61a7d..384a5c0 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -332,6 +332,7 @@ FT_BEGIN_HEADER
     TT_GlyphZoneRec  zone;     /* glyph loader points zone */
 
     FT_UInt  interpreter_version;
+    FT_UInt  hinting_engine;
 
   } TT_DriverRec;
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]