Commit c61cad868b32e6c7f8e1f3bf89719c137e52eaf8

Werner Lemberg 2015-05-22T22:02:15

[truetype] Support selector index 3 of the INSTCTRL instruction. This flag activates `native ClearType hinting', disabling backwards compatibility mode as described in Greg Hitchcocks whitepaper. In other words, it enables unrestricted functionality of all TrueType instructions in ClearType. * src/truetype/ttgload.c (tt_get_metrics): Call `sph_set_tweaks' unconditionally. (tt_loader_init): Unset `ignore_x_mode' flag if bit 2 of `GS.instruct_control' is active. * src/truetype/ttinterp.c (Ins_INSTCTRL): Handle selector index 3. (Ins_GETINFO): Updated. * docs/CHANGES: Document it.

diff --git a/ChangeLog b/ChangeLog
index 2929e7c..6b5c54c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2015-05-20  Werner Lemberg  <wl@gnu.org>
 
+	[truetype] Support selector index 3 of the INSTCTRL instruction.
+
+	This flag activates `native ClearType hinting', disabling backwards
+	compatibility mode as described in Greg Hitchcocks whitepaper.  In
+	other words, it enables unrestricted functionality of all TrueType
+	instructions in ClearType.
+
+	* src/truetype/ttgload.c (tt_get_metrics): Call `sph_set_tweaks'
+	unconditionally.
+	(tt_loader_init): Unset `ignore_x_mode' flag if bit 2 of
+	`GS.instruct_control' is active.
+
+	* src/truetype/ttinterp.c (Ins_INSTCTRL): Handle selector index 3.
+	(Ins_GETINFO): Updated.
+
+	* docs/CHANGES: Document it.
+
+2015-05-20  Werner Lemberg  <wl@gnu.org>
+
 	[truetype] Minor.
 
 	* src/truetype/ttinterp.h (SetSuperRound): Fix type of `GridPeriod'
diff --git a/docs/CHANGES b/docs/CHANGES
index 999667e..e706e1f 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -35,6 +35,9 @@ CHANGES BETWEEN 2.5.5 and 2.6
       (i.e., TTCs using  CFFs subfonts instead of TTFs),  where it may
       have a significant difference.
 
+    - Fonts natively hinted for  ClearType are now supported, properly
+      handling selector index 3 of the INSTCTRL bytecode instruction.
+
 
   III. MISCELLANEOUS
 
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index fd97009..ca07944 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -153,14 +153,16 @@
     loader->vadvance     = advance_height;
 
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+         loader->exec                                             )
     {
-      if ( loader->exec )
-        loader->exec->sph_tweak_flags = 0;
+      loader->exec->sph_tweak_flags = 0;
 
-      /* this may not be the right place for this, but it works */
-      if ( loader->exec && loader->exec->ignore_x_mode )
-        sph_set_tweaks( loader, glyph_index );
+      /* This may not be the right place for this, but it works...  */
+      /* Note that we have to unconditionally load the tweaks since */
+      /* it is possible that glyphs individually switch ClearType's */
+      /* backwards compatibility mode on and off.                   */
+      sph_set_tweaks( loader, glyph_index );
     }
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
@@ -2256,7 +2258,7 @@
         /* requires a re-execution of the CVT program                 */
         if ( grayscale != exec->grayscale )
         {
-          FT_TRACE4(( "tt_loader_init: grayscale change,"
+          FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
                       " re-executing `prep' table\n" ));
 
           exec->grayscale = grayscale;
@@ -2276,7 +2278,7 @@
           return error;
       }
 
-      /* see whether the cvt program has disabled hinting */
+      /* check whether the cvt program has disabled hinting */
       if ( exec->GS.instruct_control & 1 )
         load_flags |= FT_LOAD_NO_HINTING;
 
@@ -2284,6 +2286,11 @@
       if ( exec->GS.instruct_control & 2 )
         exec->GS = tt_default_graphics_state;
 
+      /* 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 )
+        exec->ignore_x_mode = 0;
+
       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
       loader->exec = exec;
       loader->instructions = exec->glyphIns;
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 0e536af..8ef7526 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4924,8 +4924,9 @@
 
 #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 ( SUBPIXEL_HINTING   &&
+         exc->ignore_x_mode &&
+         FT_ABS( D ) == 64  )
       D += 1;
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
@@ -5152,24 +5153,42 @@
   Ins_INSTCTRL( TT_ExecContext  exc,
                 FT_Long*        args )
   {
-    FT_Long  K, L;
+    FT_Long  K, L, Kf;
 
 
     K = args[1];
     L = args[0];
 
-    if ( K < 1 || K > 2 )
+    /* selector values cannot be `OR'ed;                 */
+    /* they are indices starting with index 1, not flags */
+    if ( K < 1 || K > 3 )
     {
       if ( exc->pedantic_hinting )
         exc->error = FT_THROW( Invalid_Reference );
       return;
     }
 
+    /* convert index to flag value */
+    Kf = 1 << ( K - 1 );
+
     if ( L != 0 )
-        L = K;
+    {
+      /* arguments to selectors look like flag values */
+      if ( L != Kf )
+      {
+        if ( exc->pedantic_hinting )
+          exc->error = FT_THROW( Invalid_Reference );
+        return;
+      }
+    }
 
-    exc->GS.instruct_control = FT_BOOL(
-      ( (FT_Byte)exc->GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
+    exc->GS.instruct_control &= ~(FT_Byte)Kf;
+    exc->GS.instruct_control |= (FT_Byte)L;
+
+    /* INSTCTRL modifying flag 3 also has an effect */
+    /* outside of the CVT program                   */
+    if ( K == 3 )
+      exc->ignore_x_mode = FT_BOOL( L == 4 );
   }
 
 
@@ -7284,11 +7303,18 @@
     /*                              */
     if ( SUBPIXEL_HINTING     &&
          ( args[0] & 1 ) != 0 &&
-         exc->ignore_x_mode   )
+         exc->subpixel        )
     {
-      K = exc->rasterizer_version;
-      FT_TRACE7(( "Setting rasterizer version %d\n",
-                  exc->rasterizer_version ));
+      if ( exc->ignore_x_mode )
+      {
+        /* if in ClearType backwards compatibility mode,        */
+        /* we sometimes change the TrueType version dynamically */
+        K = exc->rasterizer_version;
+        FT_TRACE7(( "Setting rasterizer version %d\n",
+                    exc->rasterizer_version ));
+      }
+      else
+        K = TT_INTERPRETER_VERSION_38;
     }
     else
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -7322,7 +7348,6 @@
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
 
     if ( SUBPIXEL_HINTING                                     &&
-         exc->ignore_x_mode                                   &&
          exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
     {