Tada.

Please review. I'll do my af_loader_load_glyph cleanup afterwards.

@Behdad: Please also review. Will this work for your thread-safeness
efforts?
>From 297b68621c020c8d6e61a04b8e91ac829a6bc13d Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <[email protected]>
Date: Sun, 13 Nov 2016 20:47:08 +0100
Subject: [PATCH 1/2] Implement FT_Face_Option() [1/2]

FT_Face_Option() can override certain library or module-wide options on
a face-by-face basis. These options are stored in the 'internal'
structure of a FT_Face. They are "unset" by default.

First up are custom LCD filter weights.

* Implement FT_Face_Option() and declare the option tags.

* Implement the code to honors the face-level LCD filter option.

* Make the default and light filter weights publicly accessible as
  FT_LCD_FILTER_DEFAULT_WEIGHTS and FT_LCD_FILTER_LIGHT_WEIGHTS.

* Modify the signature of FT_Bitmap_LcdFilterFunc to take FT_Byte*
  instead of FT_Library as the last argument, change _ft_lcd_filter_fir
  and _ft_lcd_filter_legacy accordingly.

* Rename _ft_lcd_filter_fir to ft_lcd_filter_fir and make it accessible
  from within the FreeType source.
---
 include/freetype/freetype.h        | 77 ++++++++++++++++++++++++++++++++++++++
 include/freetype/ftlcdfil.h        |  6 +++
 include/freetype/internal/ftobjs.h | 22 ++++++++++-
 src/base/ftlcdfil.c                | 39 ++++++++++---------
 src/base/ftobjs.c                  | 65 +++++++++++++++++++++++++++++++-
 src/smooth/ftsmooth.c              | 53 ++++++++++++++++++++------
 6 files changed, 230 insertions(+), 32 deletions(-)

diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index f3287b7..36f503b 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3578,6 +3578,83 @@ FT_BEGIN_HEADER
 
 
   /*************************************************************************/
+  /*
+   * <Function>
+   *    FT_Face_Option
+   *
+   * <Description>
+   *    This function can be used to set or override certain (library or
+   *    module-wide) options on a face-by-face basis. Useful for finer grained
+   *    control and avoiding locks on shared structures (threads can modify
+   *    their own faces as they see fit).
+   *
+   * <Input>
+   *    face       :: A handle to the source face object.
+   *    num_params :: The number of parameters that follow.
+   *    parameters :: A handle to the num_params FT_Parameters.
+   *
+   * <Return>
+   *    FreeType error code.  0~means success.
+   *
+   * <Note>
+   *    The accepted parameters are:
+   *
+   *    1) FT_FACE_OPTION_ENABLE_STEM_DARKENING:
+   *       Toggles stem darkening. Overrides the module setting.
+   *
+   *       Currently implies forcing the native CFF engine for OpenType/CFF
+   *       fonts and the (LIGHT) autohinter for all other outline formats, as
+   *       only those engines have full control over how an outline is
+   *       rendered.
+   *
+   *    2) FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS:
+   *       Sets the weights for the 5-tap in-place FIR filter used by default
+   *       (the legacy intra-pixel filter is not supported). Overrides the
+   *       library setting. See @lcd_filtering.
+   *
+   *    Pass NULL as data for a tag to reset the option and use the library or
+   *    module default again.
+   *
+   *    Example:
+   *    {
+   *        FT_Parameter parameter1;
+   *        FT_Bool darken_stems = 1;
+   *        parameter1.tag  = FT_FACE_OPTION_ENABLE_STEM_DARKENING;
+   *        parameter1.data = &darken_stems;
+   *
+   *        FT_Parameter parameter2;
+   *        FT_Byte custom_weight[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 };
+   *        parameter2.tag  = FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS;
+   *        parameter2.data = custom_weight;
+   *
+   *        FT_Parameter parameters[2] = { parameter1, parameter2 };
+   *
+   *        FT_Face_Option( face, 2, parameters );
+   *
+   *        // Switch options around.
+   *        darken_stems = 0;
+   *        ft_memcpy(parameters[1].data, FT_LCD_FILTER_LIGHT_WEIGHTS, 5);
+   *
+   *        FT_Face_Option( face, 2, parameters );
+   *
+   *        // Example for a single option.
+   *        FT_Parameter parameter3;
+   *        parameter3.tag  = FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS;
+   *        parameter3.data = NULL;
+   *
+   *        FT_Face_Option( face, 1, &parameter3 );
+   *    }
+   */
+  FT_EXPORT( FT_Error )
+  FT_Face_Option( FT_Face       face,
+                  FT_UInt       num_params,
+                  FT_Parameter* parameters);
+
+#define FT_FACE_OPTION_ENABLE_STEM_DARKENING  FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
+#define FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS FT_MAKE_TAG( 'l', 'w', 'g', 't' )
+
+
+  /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
   /*    FT_Get_Name_Index                                                  */
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index e06a895..bb85769 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -197,6 +197,12 @@ FT_BEGIN_HEADER
 
   } FT_LcdFilter;
 
+  static const FT_Byte  FT_LCD_FILTER_DEFAULT_WEIGHTS[5] =
+                            { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
+  static const FT_Byte  FT_LCD_FILTER_LIGHT_WEIGHTS[5] =
+                            { 0x00, 0x55, 0x56, 0x55, 0x00 };
+
+
 
   /**************************************************************************
    *
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 15936f2..69a56e9 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -347,6 +347,15 @@ FT_BEGIN_HEADER
   /*      created.  @FT_Reference_Face increments this counter, and        */
   /*      @FT_Done_Face only destroys a face if the counter is~1,          */
   /*      otherwise it simply decrements it.                               */
+  /*
+   *    stem_darkening ::
+   *      Overrides the module-level default, see e.g. @stem-darkening[cff]. 1
+   *      and 0 toggle on and off, -1 means to use the library default.
+   *
+   *    lcd_weights ::
+   *      Overrides the library default with custom weights for the 5-tap FIR
+   *      filter. {0, 0, 0, 0, 0} means to use the module default.
+   */
   /*                                                                       */
   typedef struct  FT_Face_InternalRec_
   {
@@ -362,6 +371,11 @@ FT_BEGIN_HEADER
 
     FT_Int              refcount;
 
+    FT_Char             stem_darkening;
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_Byte             lcd_weights[5];   /* Preset or custom filter weights. */
+#endif
   } FT_Face_InternalRec;
 
 
@@ -779,7 +793,13 @@ FT_BEGIN_HEADER
 
   typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
                                             FT_Render_Mode  render_mode,
-                                            FT_Library      library );
+                                            FT_Byte*        weights );
+
+  /* This is the default LCD filter, an in-place, 5-tap FIR filter. */
+  FT_BASE( void )
+  ft_lcd_filter_fir( FT_Bitmap*      bitmap,
+                     FT_Render_Mode  mode,
+                     FT_Byte*        weights );
 
 
   /*************************************************************************/
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 8bcbed7..c3d341c 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -30,12 +30,11 @@
 #define  USE_LEGACY
 
   /* FIR filter used by the default and light filters */
-  static void
-  _ft_lcd_filter_fir( FT_Bitmap*      bitmap,
-                      FT_Render_Mode  mode,
-                      FT_Library      library )
+  FT_BASE( void )
+  ft_lcd_filter_fir( FT_Bitmap*      bitmap,
+                     FT_Render_Mode  mode,
+                     FT_Byte*        weights )
   {
-    FT_Byte*  weights = library->lcd_weights;
     FT_UInt   width   = (FT_UInt)bitmap->width;
     FT_UInt   height  = (FT_UInt)bitmap->rows;
 
@@ -176,7 +175,7 @@
   static void
   _ft_lcd_filter_legacy( FT_Bitmap*      bitmap,
                          FT_Render_Mode  mode,
-                         FT_Library      library )
+                         FT_Byte*        weights )
   {
     FT_UInt  width  = (FT_UInt)bitmap->width;
     FT_UInt  height = (FT_UInt)bitmap->rows;
@@ -189,7 +188,7 @@
       { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
     };
 
-    FT_UNUSED( library );
+    FT_UNUSED( weights );
 
 
     /* horizontal in-place intra-pixel filter */
@@ -296,7 +295,7 @@
       return FT_THROW( Invalid_Argument );
 
     ft_memcpy( library->lcd_weights, weights, 5 );
-    library->lcd_filter_func = _ft_lcd_filter_fir;
+    library->lcd_filter_func = ft_lcd_filter_fir;
     library->lcd_extra       = 2;
 
     return FT_Err_Ok;
@@ -307,12 +306,6 @@
   FT_Library_SetLcdFilter( FT_Library    library,
                            FT_LcdFilter  filter )
   {
-    static const FT_Byte  default_filter[5] =
-                            { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
-    static const FT_Byte  light_filter[5] =
-                            { 0x00, 0x55, 0x56, 0x55, 0x00 };
-
-
     if ( !library )
       return FT_THROW( Invalid_Library_Handle );
 
@@ -324,14 +317,14 @@
       break;
 
     case FT_LCD_FILTER_DEFAULT:
-      ft_memcpy( library->lcd_weights, default_filter, 5 );
-      library->lcd_filter_func = _ft_lcd_filter_fir;
+      ft_memcpy( library->lcd_weights, FT_LCD_FILTER_DEFAULT_WEIGHTS, 5 );
+      library->lcd_filter_func = ft_lcd_filter_fir;
       library->lcd_extra       = 2;
       break;
 
     case FT_LCD_FILTER_LIGHT:
-      ft_memcpy( library->lcd_weights, light_filter, 5 );
-      library->lcd_filter_func = _ft_lcd_filter_fir;
+      ft_memcpy( library->lcd_weights, FT_LCD_FILTER_LIGHT_WEIGHTS, 5 );
+      library->lcd_filter_func = ft_lcd_filter_fir;
       library->lcd_extra       = 2;
       break;
 
@@ -356,6 +349,16 @@
 
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
+  FT_BASE( void )
+  ft_lcd_filter_fir( FT_Bitmap*      bitmap,
+                     FT_Render_Mode  mode,
+                     FT_Byte*        weights )
+  {
+    FT_UNUSED( bitmap );
+    FT_UNUSED( mode );
+    FT_UNUSED( weights );
+  }
+
   FT_EXPORT_DEF( FT_Error )
   FT_Library_SetLcdFilterWeights( FT_Library      library,
                                   unsigned char  *weights )
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index c701ebc..3d52f45 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2340,7 +2340,8 @@
 
     /* initialize internal face data */
     {
-      FT_Face_Internal  internal = face->internal;
+      FT_Face_Internal internal = face->internal;
+      static const FT_Byte lcd_weights[5] = { 0 };
 
 
       internal->transform_matrix.xx = 0x10000L;
@@ -2352,8 +2353,12 @@
       internal->transform_delta.y = 0;
 
       internal->refcount = 1;
+
+      internal->stem_darkening = -1;
+      ft_memcpy( internal->lcd_weights, lcd_weights, 5 );
     }
 
+
     if ( aface )
       *aface = face;
     else
@@ -3506,6 +3511,64 @@
 
   /* documentation is in freetype.h */
 
+  FT_EXPORT_DEF( FT_Error )
+  FT_Face_Option( FT_Face       face,
+                  FT_UInt       num_params,
+                  FT_Parameter* parameters)
+  {
+    FT_Error   error = FT_Err_Ok;
+
+
+    if ( num_params > 0 && !parameters )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    for ( ; num_params > 0; num_params-- )
+    {
+      if ( parameters->tag == FT_FACE_OPTION_ENABLE_STEM_DARKENING )
+      {
+        if ( parameters->data )
+        {
+          if ( *((FT_Bool*)parameters->data) == 1 )
+            face->internal->stem_darkening = 1;
+          else
+            face->internal->stem_darkening = 0;
+        }
+        else /* Use module default. */
+          face->internal->stem_darkening = -1;
+      }
+      else if ( parameters->tag == FT_FACE_OPTION_SET_LCD_FILTER_WEIGHTS )
+      {
+        if ( parameters->data )
+          ft_memcpy( face->internal->lcd_weights, parameters->data, 5 );
+        else /* NULL == no custom weights, use library default. Signaled by
+                filling the weight field with zeros. */
+        {
+          FT_Byte no_weight[5] = { 0 };
+          ft_memcpy( face->internal->lcd_weights, no_weight, 5 );
+        }
+      }
+      else
+      {
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
+
+      if ( error )
+        break;
+
+      parameters++;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
   FT_EXPORT_DEF( FT_UInt )
   FT_Face_GetCharVariantIndex( FT_Face   face,
                                FT_ULong  charcode,
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 1371792..03ee3ef 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -122,6 +122,38 @@
     FT_Bool  have_outline_shifted = FALSE;
     FT_Bool  have_buffer          = FALSE;
 
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_Int                   lcd_extra = 0;
+    FT_Byte                  lcd_weights[5] = { 0 };
+    const static FT_Byte     lcd_weights_empty[5] = { 0 };
+    FT_Bitmap_LcdFilterFunc  lcd_filter_func = NULL;
+
+    /* The LCD filter can be set library-wide and per-face. Face overrides
+     * library. If the face filter weights are all-zero (the default), it means
+     * that the library default should be used. */
+    if ( slot->face &&
+         ft_memcmp( slot->face->internal->lcd_weights,
+                    lcd_weights_empty,
+                    5 * sizeof(FT_Byte) ) )
+    {
+      /* A per-font filter is set. It will always use the default 5-tap
+       * in-place FIR filter that needs 2 extra pixels. */
+      lcd_filter_func = ft_lcd_filter_fir;
+      lcd_extra = 2;
+      ft_memcpy( lcd_weights, slot->face->internal->lcd_weights, 5 );
+    }
+    else
+    {
+      /* The face's lcd_weights is {0, 0, 0, 0, 0}, use library default. If the
+       * library is set to use no LCD filtering (lcd_filter_func == NULL),
+       * lcd_filter_func here will also be set to NULL and the tests further
+       * below will pass over the filtering process. */
+      lcd_filter_func = slot->library->lcd_filter_func;
+      lcd_extra = slot->library->lcd_extra;
+      ft_memcpy( lcd_weights, slot->library->lcd_weights, 5 );
+    }
+#endif
+
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
@@ -178,24 +210,21 @@
 
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
 
-    if ( slot->library->lcd_filter_func )
+    if ( lcd_filter_func )
     {
-      FT_Int  extra = slot->library->lcd_extra;
-
-
       if ( hmul )
       {
-        x_shift += 64 * ( extra >> 1 );
-        x_left  -= extra >> 1;
-        width   += 3 * extra;
+        x_shift += 64 * ( lcd_extra >> 1 );
+        x_left  -= lcd_extra >> 1;
+        width   += 3 * lcd_extra;
         pitch    = FT_PAD_CEIL( width, 4 );
       }
 
       if ( vmul )
       {
-        y_shift += 64 * ( extra >> 1 );
-        y_top   += extra >> 1;
-        height  += 3 * extra;
+        y_shift += 64 * ( lcd_extra >> 1 );
+        y_top   += lcd_extra >> 1;
+        height  += 3 * lcd_extra;
       }
     }
 
@@ -299,8 +328,8 @@
     if ( error )
       goto Exit;
 
-    if ( slot->library->lcd_filter_func )
-      slot->library->lcd_filter_func( bitmap, mode, slot->library );
+    if ( lcd_filter_func )
+      lcd_filter_func( bitmap, mode, lcd_weights );
 
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-- 
2.9.3

>From 21c01379e1d167bcd0e8f33521ba045cafe99de4 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <[email protected]>
Date: Sun, 13 Nov 2016 21:02:58 +0100
Subject: [PATCH 2/2] Implement FT_Face_Option() [2/2]

Next up is the stem darkening option.

* Rename no_stem_darkening to stem_darkening internally and change the
  logic around it because it simplifies the code a bit.

* Honor the face-level option in the CFF driver and autohinter.

* Change FT_Load_Glyph() to trigger the autohinter for font drivers that
  can't darken stems by themselves. This currently means all of them
  except for the CFF driver. Within the autohinter, enforce LIGHT mode
  because stem darkening currently only really works there.
---
 src/autofit/afloader.c | 10 +++++++++-
 src/autofit/afmodule.c | 16 ++++++++--------
 src/autofit/afmodule.h |  2 +-
 src/base/ftobjs.c      | 28 +++++++++++++++++++++++++---
 src/cff/cf2ft.c        |  7 ++++++-
 src/cff/cffdrivr.c     | 14 +++++++-------
 src/cff/cffobjs.c      |  2 +-
 src/cff/cffobjs.h      |  2 +-
 8 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 26bba06..91fdfe0 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -135,7 +135,9 @@
      * must therefore be recomputed for each size and
      * `standard_{vertical,horizontal}_width' change.
      */
-    if ( !module->no_stem_darkening )
+    if ( face->internal->stem_darkening == 1 ||
+         ( face->internal->stem_darkening < 0 &&
+           module->stem_darkening ) )
     {
       AF_FaceGlobals         globals = loader->globals;
       AF_WritingSystemClass  writing_system_class;
@@ -492,6 +494,12 @@
     scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
     scaler.flags       = 0;  /* XXX: fix this */
 
+    /* Stem darkening only works well in LIGHT mode. */
+    if ( face->internal->stem_darkening == 1 ||
+         ( face->internal->stem_darkening < 0 &&
+           module->stem_darkening ) )
+      scaler.render_mode = FT_RENDER_MODE_LIGHT;
+
     error = af_loader_reset( loader, module, face );
     if ( !error )
     {
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index f325ebf..1d378fb 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -292,19 +292,19 @@
 
 
         if ( nsd == 0 )
-          module->no_stem_darkening = 0;
+          module->stem_darkening = 1;
         else if ( nsd == 1 )
-          module->no_stem_darkening = 1;
+          module->stem_darkening = 0;
         else
           return FT_THROW( Invalid_Argument );
       }
       else
 #endif
       {
-        FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+        FT_Bool*  stem_darkening = (FT_Bool*)value;
 
 
-        module->no_stem_darkening = *no_stem_darkening;
+        module->stem_darkening = !*stem_darkening;
       }
 
       return error;
@@ -404,11 +404,11 @@
     }
     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
     {
-      FT_Bool   no_stem_darkening = module->no_stem_darkening;
-      FT_Bool*  val               = (FT_Bool*)value;
+      FT_Bool   stem_darkening = module->stem_darkening;
+      FT_Bool*  val            = (FT_Bool*)value;
 
 
-      *val = no_stem_darkening;
+      *val = !stem_darkening;
 
       return error;
     }
@@ -465,7 +465,7 @@
 #ifdef AF_CONFIG_OPTION_USE_WARPER
     module->warping           = 0;
 #endif
-    module->no_stem_darkening = TRUE;
+    module->stem_darkening = FALSE;
 
     module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
     module->darken_params[1]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index e65db5f..35c3041 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -41,7 +41,7 @@ FT_BEGIN_HEADER
 #ifdef AF_CONFIG_OPTION_USE_WARPER
     FT_Bool       warping;
 #endif
-    FT_Bool       no_stem_darkening;
+    FT_Bool       stem_darkening;
     FT_Int        darken_params[8];
 
   } AF_ModuleRec, *AF_Module;
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 3d52f45..5d23210 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -612,7 +612,9 @@
     FT_Bool       autohint = FALSE;
     FT_Module     hinter;
     TT_Face       ttface = (TT_Face)face;
-
+    FT_Bool       driver_can_darken_stems = 0;
+    FT_Bool       stem_darkening = 0;
+    FT_Bool       stem_darkening_driver = 0;
 
     if ( !face || !face->size || !face->glyph )
       return FT_THROW( Invalid_Face_Handle );
@@ -627,8 +629,27 @@
     library = driver->root.library;
     hinter  = library->auto_hinter;
 
-    /* resolve load flags dependencies */
+    /* Determine if stem darkening is to be applied. */
+    error = FT_Property_Get( library, driver->clazz->root.module_name,
+                             "no-stem-darkening", &stem_darkening_driver );
+    if ( error )
+    {
+      driver_can_darken_stems = FALSE;
+      stem_darkening_driver   = FALSE;
+    }
+    else
+    {
+      driver_can_darken_stems = TRUE;
+      stem_darkening_driver   = !stem_darkening_driver;
+    }
+
+    error = FT_Err_Ok; /* Reset error variable. */
 
+    stem_darkening = ( face->internal->stem_darkening == 1 ||
+                       ( face->internal->stem_darkening < 0 &&
+                         stem_darkening_driver ) );
+
+    /* resolve load flags dependencies */
     if ( load_flags & FT_LOAD_NO_RECURSE )
       load_flags |= FT_LOAD_NO_SCALE         |
                     FT_LOAD_IGNORE_TRANSFORM;
@@ -691,6 +712,7 @@
         /* both `fpgm' and `prep' tables are missing                 */
         if ( ( mode == FT_RENDER_MODE_LIGHT                   &&
                !FT_DRIVER_HINTS_LIGHTLY( driver ) )             ||
+             ( stem_darkening && !driver_can_darken_stems )     ||
              ( FT_IS_SFNT( face )                             &&
                ttface->num_locations                          &&
                ttface->max_profile.maxSizeOfInstructions == 0 &&
@@ -4211,7 +4233,7 @@
       parameters++;
     }
 
-  Exit:
+		Exit:
     return error;
   }
 
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index edbe6a7..a1b70a5 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -339,6 +339,9 @@
       CFF_Builder*  builder = &decoder->builder;
       CFF_Driver    driver  = (CFF_Driver)FT_FACE_DRIVER( builder->face );
 
+      FT_Bool stem_darkening_driver = driver->stem_darkening;
+      FT_Char stem_darkening_font   = builder->face->root.internal->stem_darkening;
+
       /* local error */
       FT_Error       error2 = FT_Err_Ok;
       CF2_BufferRec  buf;
@@ -369,7 +372,9 @@
       font->renderingFlags = 0;
       if ( hinted )
         font->renderingFlags |= CF2_FlagsHinted;
-      if ( scaled && !driver->no_stem_darkening )
+      if ( scaled && ( stem_darkening_font == 1 ||
+                       ( stem_darkening_font < 0 &&
+                         stem_darkening_driver ) ) )
         font->renderingFlags |= CF2_FlagsDarkened;
 
       font->darkenParams[0] = driver->darken_params[0];
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index cf02477..5034d14 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -780,19 +780,19 @@
 
 
         if ( nsd == 0 )
-          driver->no_stem_darkening = 0;
+          driver->stem_darkening = 1;
         else if ( nsd == 1 )
-          driver->no_stem_darkening = 1;
+          driver->stem_darkening = 0;
         else
           return FT_THROW( Invalid_Argument );
       }
       else
 #endif
       {
-        FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+        FT_Bool*  stem_darkening = (FT_Bool*)value;
 
 
-        driver->no_stem_darkening = *no_stem_darkening;
+        driver->stem_darkening = !*stem_darkening;
       }
 
       return error;
@@ -842,11 +842,11 @@
     }
     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
     {
-      FT_Bool   no_stem_darkening = driver->no_stem_darkening;
-      FT_Bool*  val               = (FT_Bool*)value;
+      FT_Bool   stem_darkening = driver->stem_darkening;
+      FT_Bool*  val            = (FT_Bool*)value;
 
 
-      *val = no_stem_darkening;
+      *val = !stem_darkening;
 
       return error;
     }
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 126bbee..268a188 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -1095,7 +1095,7 @@
     driver->hinting_engine = FT_CFF_HINTING_ADOBE;
 #endif
 
-    driver->no_stem_darkening = TRUE;
+    driver->stem_darkening = FALSE;
 
     driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
     driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index 9dc7753..80b36b4 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -119,7 +119,7 @@ FT_BEGIN_HEADER
     FT_DriverRec  root;
 
     FT_UInt  hinting_engine;
-    FT_Bool  no_stem_darkening;
+    FT_Bool  stem_darkening;
 
     FT_Int  darken_params[8];
 
-- 
2.9.3

_______________________________________________
Freetype-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to