Blob Blame History Raw
From a0455468fdb8dd1959596d0c8c8a3ff07ee495a3 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madigens@gmail.com>
Date: Sat, 20 May 2017 07:28:46 +0200
Subject: [truetype] Always use interpreter v35 for B/W rendering (#51051).

* src/truetype/ttgload.c (tt_loader_init)
[TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL]: Adjust
`subpixel_hinting_lean', `grayscale_cleartype', and
`vertical_lcd_lean' accordingly.

* src/truetype/ttinterp.c (Ins_GETINFO): Updated.
(TT_RunIns): Update `backward_compatibility' flag.

diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 68a9b4ad5..e5a3da37a 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -2339,13 +2339,19 @@
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
       {
-        subpixel_hinting_lean   = TRUE;
-        grayscale_cleartype     = !FT_BOOL( load_flags         &
-                                            FT_LOAD_TARGET_LCD     ||
-                                            load_flags           &
-                                            FT_LOAD_TARGET_LCD_V   );
-        exec->vertical_lcd_lean = FT_BOOL( load_flags           &
-                                           FT_LOAD_TARGET_LCD_V );
+        subpixel_hinting_lean =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   FT_RENDER_MODE_MONO               );
+        grayscale_cleartype =
+          FT_BOOL( subpixel_hinting_lean         &&
+                   !( ( load_flags         &
+                        FT_LOAD_TARGET_LCD )   ||
+                      ( load_flags           &
+                        FT_LOAD_TARGET_LCD_V ) ) );
+        exec->vertical_lcd_lean =
+          FT_BOOL( subpixel_hinting_lean    &&
+                   ( load_flags           &
+                     FT_LOAD_TARGET_LCD_V ) );
       }
       else
       {
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index af31408cb..0c48c2562 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -7345,7 +7345,7 @@
       /*                              */
       /* The only smoothing method FreeType supports unless someone sets */
       /* FT_LOAD_TARGET_MONO.                                            */
-      if ( ( args[0] & 2048 ) != 0 )
+      if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
         K |= 1 << 18;
 
       /********************************/
@@ -7589,11 +7589,21 @@
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
-    /* Toggle backward 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.  Backward compatibility     */
-    /* hacks may break it.                                                 */
+    /*
+     *  Toggle backward compatibility according to what font wants, except
+     *  when
+     *
+     *  1) we have a `tricky' font that heavily relies on the interpreter to
+     *     render glyphs correctly, for example DFKai-SB, or
+     *  2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+     *
+     *  In those cases, backward compatibility needs to be turned off to get
+     *  correct rendering.  The rendering is then completely up to the
+     *  font's programming.
+     *
+     */
     if ( SUBPIXEL_HINTING_MINIMAL          &&
+         exc->subpixel_hinting_lean        &&
          !FT_IS_TRICKY( &exc->face->root ) )
       exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
     else
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 55e472091..abbecfcee 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -253,23 +253,38 @@ FT_BEGIN_HEADER
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     /*
-     * Modern TrueType fonts are usually rendered through Microsoft's
-     * collection of rendering techniques called ClearType (e.g., subpixel
-     * rendering and subpixel hinting).  When ClearType was introduced, most
-     * fonts were not ready.  Microsoft decided to implement a backward
-     * 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 supports ClearType-like hinting of TrueType fonts through
+     * the version 40 interpreter.  This is achieved through several hacks
+     * in the base (v35) interpreter, as detailed below.
      *
-     * The minimal subpixel hinting code (interpreter version 40) employs a
-     * small list of font-agnostic hacks to bludgeon non-native-ClearType
-     * fonts (except tricky ones[1]) into submission.  It will not try to
-     * toggle hacks for specific fonts for performance and complexity
-     * reasons.  The focus is on modern (web)fonts rather than legacy fonts
-     * that were made for black-and-white rendering.
+     * ClearType is an umbrella term for several rendering techniques
+     * employed by Microsoft's various GUI and rendering toolkit
+     * implementations, most importantly: subpixel rendering for using the
+     * RGB subpixels of LCDs to approximately triple the perceived
+     * resolution on the x-axis and subpixel hinting for positioning stems
+     * on subpixel borders.  TrueType programming is explicit, i.e., fonts
+     * must be programmed to take advantage of ClearType's possibilities.
+     *
+     * When ClearType was introduced, it seemed unlikely that all fonts
+     * would be reprogrammed, so Microsoft decided to implement a backward
+     * compatibility mode.  It employs several simple to complicated
+     * assumptions and tricks, many of them font-dependent, that modify the
+     * interpretation of the bytecode contained in these fonts to retrofit
+     * them into a ClearType-y look.  The quality of the results varies.
+     * Most (web)fonts that were released since then have come to rely on
+     * these hacks to render correctly, even some of Microsoft's flagship
+     * fonts (e.g., Calibri, Cambria, Segoe UI).
+     *
+     * FreeType's minimal subpixel hinting code (interpreter version 40)
+     * employs a small list of font-agnostic hacks loosely based on the
+     * public information available on Microsoft's compatibility mode[2].
+     * The focus is on modern (web)fonts rather than legacy fonts that were
+     * made for monochrome rendering.  It will not match ClearType rendering
+     * exactly.  Unlike the `Infinality' code (interpreter version 38) that
+     * came before, it will not try to toggle hacks for specific fonts for
+     * performance and complexity reasons.  It will fall back to version 35
+     * behavior for tricky fonts[1] or when monochrome rendering is
+     * requested.
      *
      * Major hacks
      *
@@ -347,7 +362,8 @@ FT_BEGIN_HEADER
      *
      */
 
-    /* Using v40 implies subpixel hinting.  Used to detect interpreter */
+    /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been
+     * requested.  Used to detect interpreter */
     /* version switches.  `_lean' to differentiate from the Infinality */
     /* `subpixel_hinting', which is managed differently.               */
     FT_Bool            subpixel_hinting_lean;