Commit 02e80da6090c21d6e59ac955b7f56e1ad4a9850b

Alexei Podtelezhnikov 2017-09-24T22:18:34

Tweak per-face LCD filtering controls. Thing are simpler with a NULL-function pointer. * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New pointer to the filter function. (FT_LibraryRec): Remove unused `lcd_filter'. (FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir): Move from here... * include/freetype/ftlcdfil.h (FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir): ... to here. * src/base/ftobjs.c (ft_open_face_internal): NULL-initialize the per-face filter. (FT_Face_Properties): Set it. * src/smooth/ftsmooth.c (ft_smooth_render_generic): Simplify. * src/base/ftlcdfil.c (ft_lcd_filter_fir, FT_Libary_SetLcdFilter): Minor.

diff --git a/ChangeLog b/ChangeLog
index 47811d1..d42f986 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2017-09-24  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	Tweak per-face LCD filtering controls.
+
+	Thing are simpler with a NULL-function pointer.
+
+	* include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New
+	pointer to the filter function.
+	(FT_LibraryRec): Remove unused `lcd_filter'.
+	(FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir):  Move from here...
+	* include/freetype/ftlcdfil.h (FT_Bitmap_LcdFilterFunc,
+	ft_lcd_filter_fir): ... to here.
+
+	* src/base/ftobjs.c (ft_open_face_internal): NULL-initialize the
+	per-face filter.
+	(FT_Face_Properties): Set it.
+	* src/smooth/ftsmooth.c (ft_smooth_render_generic): Simplify.
+
+	* src/base/ftlcdfil.c (ft_lcd_filter_fir, FT_Libary_SetLcdFilter):
+	Minor.
+
 2017-09-24  Jonathan Kew  <jfkthame@gmail.com>
 
 	[sfnt] Fix `premultiply_data' (#52092).
@@ -32,7 +53,7 @@
 	VariationIndex subtable.
 	(otv_Lookup_validate): Handle MarkFilteringSet.
 
-2017-09-21  Alexei Podtelezhnikov  <apodtele@gmail.com>
+2017-09-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	[build] Windows-style DLL versioning.
 
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index ea4a66e..8c75141 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -316,6 +316,17 @@ FT_BEGIN_HEADER
 
   typedef FT_Byte  FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
 
+  typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
+                                            FT_Render_Mode  render_mode,
+                                            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_LcdFiveTapFilter  weights );
+
 
   /* */
 
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 4231be2..25c328f 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -369,9 +369,10 @@ FT_BEGIN_HEADER
   /*      operator.  Value~0 means to use the font's value.  Value~-1      */
   /*      means to use the CFF driver's 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 library default. */
+  /*    lcd_weights      ::                                                */
+  /*    lcd_filter_func  ::                                                */
+  /*      If subpixel rendering is activated, the LCD filtering weights    */
+  /*      and callback function.                                           */
   /*                                                                       */
   /*    refcount ::                                                        */
   /*      A counter initialized to~1 at the time an @FT_Face structure is  */
@@ -393,8 +394,10 @@ FT_BEGIN_HEADER
 
     FT_Char              no_stem_darkening;
     FT_Int32             random_seed;
+
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-    FT_LcdFiveTapFilter  lcd_weights;  /* preset or custom filter weights */
+    FT_LcdFiveTapFilter      lcd_weights;      /* filter weights, if any */
+    FT_Bitmap_LcdFilterFunc  lcd_filter_func;  /* filtering callback     */
 #endif
 
     FT_Int  refcount;
@@ -821,18 +824,6 @@ FT_BEGIN_HEADER
 #define FT_DEBUG_HOOK_TRUETYPE  0
 
 
-  typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
-                                            FT_Render_Mode  render_mode,
-                                            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_LcdFiveTapFilter  weights );
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
@@ -878,9 +869,6 @@ FT_BEGIN_HEADER
   /*                        interpreter.  Currently, only the TrueType     */
   /*                        bytecode debugger uses this.                   */
   /*                                                                       */
-  /*    lcd_filter       :: If subpixel rendering is activated, the        */
-  /*                        selected LCD filter mode.                      */
-  /*                                                                       */
   /*    lcd_weights      :: If subpixel rendering is activated, the LCD    */
   /*                        filter weights, if any.                        */
   /*                                                                       */
@@ -915,7 +903,6 @@ FT_BEGIN_HEADER
     FT_DebugHook_Func  debug_hooks[4];
 
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-    FT_LcdFilter             lcd_filter;
     FT_LcdFiveTapFilter      lcd_weights;      /* filter weights, if any */
     FT_Bitmap_LcdFilterFunc  lcd_filter_func;  /* filtering callback     */
 #endif
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 60c813f..ca781f3 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -32,7 +32,7 @@
 #define FT_SHIFTCLAMP( x )  ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
 
   /* FIR filter used by the default and light filters */
-  FT_BASE( void )
+  FT_BASE_DEF( void )
   ft_lcd_filter_fir( FT_Bitmap*           bitmap,
                      FT_Render_Mode       mode,
                      FT_LcdFiveTapFilter  weights )
@@ -305,8 +305,6 @@
       return FT_THROW( Invalid_Argument );
     }
 
-    library->lcd_filter = filter;
-
     return FT_Err_Ok;
   }
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 6db8136..aedb1f3 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2441,7 +2441,8 @@
       internal->no_stem_darkening = -1;
 
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-      ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS );
+      /* Per-face filtering can only be set up by FT_Face_Properties */
+      internal->lcd_filter_func = NULL;
 #endif
     }
 
@@ -3653,16 +3654,11 @@
       {
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
         if ( properties->data )
+        {
           ft_memcpy( face->internal->lcd_weights,
                      properties->data,
                      FT_LCD_FILTER_FIVE_TAPS );
-        else
-        {
-          /* Value NULL indicates `no custom weights, use library        */
-          /* defaults', signaled by filling the weight field with zeros. */
-          ft_memset( face->internal->lcd_weights,
-                     0,
-                     FT_LCD_FILTER_FIVE_TAPS );
+          face->internal->lcd_filter_func = ft_lcd_filter_fir;
         }
 #else
         error = FT_THROW( Unimplemented_Feature );
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 963435d..99a9883 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -115,56 +115,22 @@
     FT_Bool  have_buffer          = FALSE;
 
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_Byte*                 lcd_weights;
+    FT_Bitmap_LcdFilterFunc  lcd_filter_func;
 
-    FT_LcdFiveTapFilter      lcd_weights        = { 0 };
-    FT_Bool                  have_custom_weight = FALSE;
-    FT_Bitmap_LcdFilterFunc  lcd_filter_func    = NULL;
 
-
-    if ( slot->face )
+    /* Per-face LCD filtering takes priority if set up. */
+    if ( slot->face && slot->face->internal->lcd_filter_func )
     {
-      FT_Char  i;
-
-
-      for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ )
-        if ( slot->face->internal->lcd_weights[i] != 0 )
-        {
-          have_custom_weight = TRUE;
-          break;
-        }
-    }
-
-    /*
-     * 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 ( have_custom_weight )
-    {
-      /*
-       * A per-font filter is set.  It always uses the default 5-tap
-       * in-place FIR filter.
-       */
-      ft_memcpy( lcd_weights,
-                 slot->face->internal->lcd_weights,
-                 FT_LCD_FILTER_FIVE_TAPS );
-      lcd_filter_func = ft_lcd_filter_fir;
+      lcd_weights     = slot->face->internal->lcd_weights;
+      lcd_filter_func = slot->face->internal->lcd_filter_func;
     }
     else
     {
-      /*
-       * The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library
-       * default'.  If the library is set to use no LCD filtering
-       * (lcd_filter_func == NULL), `lcd_filter_func' here is also set to
-       * NULL and the tests further below pass over the filtering process.
-       */
-      ft_memcpy( lcd_weights,
-                 slot->library->lcd_weights,
-                 FT_LCD_FILTER_FIVE_TAPS );
+      lcd_weights     = slot->library->lcd_weights;
       lcd_filter_func = slot->library->lcd_filter_func;
     }
-
-#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
@@ -208,7 +174,7 @@
 #else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
     /* add minimal padding for LCD filter depending on specific weights */
-    if ( lcd_filter_func )
+    if ( lcd_filter_func == ft_lcd_filter_fir )
     {
       if ( hmul )
       {