Commit d682e510627086df010b0677003f8ac5e612e913

Nikolaus Waxweiler 2015-11-02T09:06:36

[autofit] Add stem-darkening properties. Actual code follows in a later commit. * include/freetype/ftautoh.h: Document `no-stem-darkening' and `darkening-parameters'. * src/autofit/afmodule.h: New fields `no_stem_darkening' and `darken_params'. * src/autofit/afmodule.c (af_property_set, af_property_get): Handle them. (af_autofitter_init): Initialize them.

diff --git a/ChangeLog b/ChangeLog
index ee5e5e9..5286c87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2015-11-02  Nikolaus Waxweiler  <madigens@gmail.com>
+
+	[autofit] Add stem-darkening properties.
+
+	Actual code follows in a later commit.
+
+	* include/freetype/ftautoh.h: Document `no-stem-darkening' and
+	`darkening-parameters'.
+
+	* src/autofit/afmodule.h: New fields `no_stem_darkening' and
+	`darken_params'.
+
+	* src/autofit/afmodule.c (af_property_set, af_property_get):
+	Handle them.
+	(af_autofitter_init): Initialize them.
+
 2015-11-02  Bungeman  <bungeman@gmail.com>
 
 	[ftfuzzer] Add support for multiple files (patch #8779).
diff --git a/include/freetype/ftautoh.h b/include/freetype/ftautoh.h
index ab39c21..e4c1eae 100644
--- a/include/freetype/ftautoh.h
+++ b/include/freetype/ftautoh.h
@@ -439,6 +439,58 @@ FT_BEGIN_HEADER
    */
 
 
+  /**************************************************************************
+   *
+   * @property:
+   *   no-stem-darkening
+   *
+   * @description:
+   *   *Experimental* *only*
+   *
+   *   The main purpose of emboldening glyphs or `stem darkening' is to
+   *   enhance readability at smaller sizes.  The smaller the size, the more
+   *   emboldening is applied to keep glyphs from `thinning out'.  All
+   *   glyphs that pass through the autohinter will be emboldened unless
+   *   this property is set to TRUE.
+   *
+   *   See the description of the CFF driver for algorithmic details.  Total
+   *   consistency with the CFF driver is currently not achieved because the
+   *   emboldening method differs and glyphs must be scaled down on the
+   *   Y-axis to keep outline points inside their precomputed blue zones.
+   *   The smaller the size (especially 9ppem and down), the higher the loss
+   *   of emboldening versus the CFF driver.
+   *
+   *   *ATTENTION*: This feature has been developed with linear alpha
+   *   blending and gamma correction of glyphs in mind: A rendering library
+   *   must apply linear alpha blending while compositing glyph bitmaps onto
+   *   a surface and then apply gamma correction to the glyph pixels to get
+   *   from linear space to display space (unless the display works in
+   *   linear space).  Internal testing at Adobe found that a gamma
+   *   correction value of 1.8 gives good results across a wide range of
+   *   displays with a sRGB gamma curve or a similar one.
+   *
+   *   If this is not possible, it might be better to disable stem
+   *   darkening.  Currently, this can only be done globally.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   darkening-parameters
+   *
+   * @description:
+   *   *Experimental* *only*
+   *
+   *   See the description of the CFF driver for details.  This
+   *   implementation appropriates the
+   *   CFF_CONFIG_OPTION_DARKENING_PARAMETER_* #defines for consistency.
+   *   Note the differences described in @no-stem-darkening.
+   *
+   */
+
+
   /* */
 
 
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index 2c759da..6bb8193 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -177,6 +177,46 @@
       return error;
     }
 #endif /* AF_CONFIG_OPTION_USE_WARPER */
+    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = (FT_Int*)value;
+
+      FT_Int  x1 = darken_params[0];
+      FT_Int  y1 = darken_params[1];
+      FT_Int  x2 = darken_params[2];
+      FT_Int  y2 = darken_params[3];
+      FT_Int  x3 = darken_params[4];
+      FT_Int  y3 = darken_params[5];
+      FT_Int  x4 = darken_params[6];
+      FT_Int  y4 = darken_params[7];
+
+
+      if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
+           y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
+           x1 > x2  || x2 > x3  || x3 > x4              ||
+           y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+        return FT_THROW( Invalid_Argument );
+
+      module->darken_params[0] = x1;
+      module->darken_params[1] = y1;
+      module->darken_params[2] = x2;
+      module->darken_params[3] = y2;
+      module->darken_params[4] = x3;
+      module->darken_params[5] = y3;
+      module->darken_params[6] = x4;
+      module->darken_params[7] = y4;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+    {
+      FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+
+
+      module->no_stem_darkening = *no_stem_darkening;
+
+      return error;
+    }
 
     FT_TRACE0(( "af_property_set: missing property `%s'\n",
                 property_name ));
@@ -253,6 +293,33 @@
       return error;
     }
 #endif /* AF_CONFIG_OPTION_USE_WARPER */
+    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = module->darken_params;
+      FT_Int*  val           = (FT_Int*)value;
+
+
+      val[0] = darken_params[0];
+      val[1] = darken_params[1];
+      val[2] = darken_params[2];
+      val[3] = darken_params[3];
+      val[4] = darken_params[4];
+      val[5] = darken_params[5];
+      val[6] = darken_params[6];
+      val[7] = darken_params[7];
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+    {
+      FT_Bool   no_stem_darkening = module->no_stem_darkening;
+      FT_Bool*  val               = (FT_Bool*)value;
+
+
+      *val = no_stem_darkening;
+
+      return error;
+    }
 
     FT_TRACE0(( "af_property_get: missing property `%s'\n",
                 property_name ));
@@ -299,11 +366,21 @@
     AF_Module  module = (AF_Module)ft_module;
 
 
-    module->fallback_style = AF_STYLE_FALLBACK;
-    module->default_script = AF_SCRIPT_DEFAULT;
+    module->fallback_style    = AF_STYLE_FALLBACK;
+    module->default_script    = AF_SCRIPT_DEFAULT;
 #ifdef AF_CONFIG_OPTION_USE_WARPER
-    module->warping        = 0;
+    module->warping           = 0;
 #endif
+    module->no_stem_darkening = FALSE;
+
+    module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+    module->darken_params[1]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+    module->darken_params[2]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+    module->darken_params[3]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+    module->darken_params[4]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+    module->darken_params[5]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+    module->darken_params[6]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+    module->darken_params[7]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
 
     return FT_Err_Ok;
   }
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index b9c2fd8..3c61d89 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -41,6 +41,8 @@ FT_BEGIN_HEADER
 #ifdef AF_CONFIG_OPTION_USE_WARPER
     FT_Bool       warping;
 #endif
+    FT_Bool       no_stem_darkening;
+    FT_Int        darken_params[8];
 
   } AF_ModuleRec, *AF_Module;