freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] master 2e95198 2/9: Add face property for LCD filter weights


From: Werner LEMBERG
Subject: [freetype2] master 2e95198 2/9: Add face property for LCD filter weights.
Date: Mon, 20 Feb 2017 03:16:24 -0500 (EST)

branch: master
commit 2e9519885b8e7e5fdc9d75b35992ef7bbf15e53a
Author: Nikolaus Waxweiler <address@hidden>
Commit: Werner Lemberg <address@hidden>

    Add face property for LCD filter weights.
    
    * include/freetype/ftlcdfil.h (FT_PARAM_TAG_LCD_FILTER_WEIGHTS,
    FT_LCD_FILTER_FIVE_TAPS): New macros.
    (FT_LcdFiveTapFilter): New typedef.
    
    * include/freetype/ftobjs.h (FT_Face_InternalRec)
    [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add `lcd_weights' field.
    (FT_Bitmap_LcdFilterFunc): Change third argument to weights array.
    (ft_lcd_filter_fir): New prototype.
    (FT_LibraryRec): Updated.
    
    * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Renamed to...
    (ft_lcd_filter_dir): ... this base function.
    Updated.
    (_ft_lcd_filter_legacy): Updated.
    (FT_Library_SetLcdFilterWeights, FT_Library_SetLcdFilter): Updated.
    
    * src/base/ftobjs.c (ft_open_face_internal): Updated.
    (FT_Face_Properties): Handle FT_PARAM_TAG_LCD_FILTER_WEIGHTS.
    
    * src/smooth/ftsmooth.c (ft_smooth_render_generic)
    [FT_CONFIG_OPTION_SUBPIXEL_RENDERING: Handle LCD weights from
    `FT_Face_Internal'.
---
 ChangeLog                          | 28 ++++++++++++++
 include/freetype/freetype.h        |  6 +++
 include/freetype/ftlcdfil.h        | 31 +++++++++++++++
 include/freetype/internal/ftobjs.h | 21 +++++++++--
 src/base/ftlcdfil.c                | 52 +++++++++++++++----------
 src/base/ftobjs.c                  | 31 ++++++++++++++-
 src/smooth/ftsmooth.c              | 77 +++++++++++++++++++++++++++++++-------
 7 files changed, 208 insertions(+), 38 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9008b6b..f2b4dc1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2017-02-16  Nikolaus Waxweiler  <address@hidden>
+           Werner Lemberg  <address@hidden>
+
+       Add face property for LCD filter weights.
+
+       * include/freetype/ftlcdfil.h (FT_PARAM_TAG_LCD_FILTER_WEIGHTS,
+       FT_LCD_FILTER_FIVE_TAPS): New macros.
+       (FT_LcdFiveTapFilter): New typedef.
+
+       * include/freetype/ftobjs.h (FT_Face_InternalRec)
+       [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add `lcd_weights' field.
+       (FT_Bitmap_LcdFilterFunc): Change third argument to weights array.
+       (ft_lcd_filter_fir): New prototype.
+       (FT_LibraryRec): Updated.
+
+       * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Renamed to...
+       (ft_lcd_filter_dir): ... this base function.
+       Updated.
+       (_ft_lcd_filter_legacy): Updated.
+       (FT_Library_SetLcdFilterWeights, FT_Library_SetLcdFilter): Updated.
+
+       * src/base/ftobjs.c (ft_open_face_internal): Updated.
+       (FT_Face_Properties): Handle FT_PARAM_TAG_LCD_FILTER_WEIGHTS.
+
+       * src/smooth/ftsmooth.c (ft_smooth_render_generic)
+       [FT_CONFIG_OPTION_SUBPIXEL_RENDERING: Handle LCD weights from
+       `FT_Face_Internal'.
+
 2017-02-14  Nikolaus Waxweiler  <address@hidden>
            Werner Lemberg  <address@hidden>
 
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index fd7d445..b902bc5 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3629,6 +3629,12 @@ FT_BEGIN_HEADER
    *   Note that only a subset of the available properties can be
    *   controlled.
    *
+   *   * LCD filter weights (@FT_PARAM_TAG_LCD_FILTER_WEIGHTS, corresponding
+   *     to function @FT_Library_SetLcdFilterWeights).
+   *
+   *   Pass NULL as `data' in @FT_Parameter for a given tag to reset the
+   *   option and use the library or module default again.
+   *
    * @input:
    *   face ::
    *     A handle to the source face object.
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 928bb0f..181d4db 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -275,6 +275,37 @@ FT_BEGIN_HEADER
   FT_Library_SetLcdFilterWeights( FT_Library      library,
                                   unsigned char  *weights );
 
+
+  /*
+   * @constant:
+   *   FT_PARAM_TAG_LCD_FILTER_WEIGHTS
+   *
+   * @description:
+   *   An @FT_Parameter tag to be used with @FT_Face_Properties.  The
+   *   corresponding argument specifies the five LCD filter weights for a
+   *   given face (if using @FT_LOAD_TARGET_LCD, for example), overriding
+   *   the global default values or the values set up with
+   *   @FT_Library_Set_LcdFilterWeights.
+   *
+   */
+#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
+          FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
+
+
+  /*
+   * @type:
+   *   FT_LcdFiveTapFilter
+   *
+   * @description:
+   *   A typedef for passing the five LCD filter weights to
+   *   @FT_Face_Properties within an @FT_Parameter structure.
+   *
+   */
+#define FT_LCD_FILTER_FIVE_TAPS  5
+
+  typedef FT_Byte  FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
+
+
   /* */
 
 
diff --git a/include/freetype/internal/ftobjs.h 
b/include/freetype/internal/ftobjs.h
index 772d82c..cd2697e 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -348,6 +348,10 @@ FT_BEGIN_HEADER
   /*      @FT_Done_Face only destroys a face if the counter is~1,          */
   /*      otherwise it simply decrements it.                               */
   /*                                                                       */
+  /*    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. */
+  /*                                                                       */
   typedef struct  FT_Face_InternalRec_
   {
     FT_Matrix           transform_matrix;
@@ -362,6 +366,10 @@ FT_BEGIN_HEADER
 
     FT_Int              refcount;
 
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_LcdFiveTapFilter  lcd_weights;  /* preset or custom filter weights */
+#endif
+
   } FT_Face_InternalRec;
 
 
@@ -775,12 +783,19 @@ FT_BEGIN_HEADER
 
   /* This hook is used by the TrueType debugger.  It must be set to an */
   /* alternate truetype bytecode interpreter function.                 */
-#define FT_DEBUG_HOOK_TRUETYPE            0
+#define FT_DEBUG_HOOK_TRUETYPE  0
 
 
   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_LcdFiveTapFilter  weights );
 
 
   /*************************************************************************/
@@ -876,7 +891,7 @@ FT_BEGIN_HEADER
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     FT_LcdFilter             lcd_filter;
     FT_Int                   lcd_extra;        /* number of extra pixels */
-    FT_Byte                  lcd_weights[5];   /* filter weights, if any */
+    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 f8e1709..611b39f 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -30,14 +30,13 @@
 #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_LcdFiveTapFilter  weights )
   {
-    FT_Byte*  weights = library->lcd_weights;
-    FT_UInt   width   = (FT_UInt)bitmap->width;
-    FT_UInt   height  = (FT_UInt)bitmap->rows;
+    FT_UInt  width   = (FT_UInt)bitmap->width;
+    FT_UInt  height  = (FT_UInt)bitmap->rows;
 
 
     /* horizontal in-place FIR filter */
@@ -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 */
@@ -295,8 +294,8 @@
     if ( !weights )
       return FT_THROW( Invalid_Argument );
 
-    ft_memcpy( library->lcd_weights, weights, 5 );
-    library->lcd_filter_func = _ft_lcd_filter_fir;
+    ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS );
+    library->lcd_filter_func = ft_lcd_filter_fir;
     library->lcd_extra       = 2;
 
     return FT_Err_Ok;
@@ -307,10 +306,10 @@
   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 };
+    static const FT_LcdFiveTapFilter  default_weights =
+                   { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
+    static const FT_LcdFiveTapFilter  light_weights =
+                   { 0x00, 0x55, 0x56, 0x55, 0x00 };
 
 
     if ( !library )
@@ -324,14 +323,18 @@
       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,
+                 default_weights,
+                 FT_LCD_FILTER_FIVE_TAPS );
+      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,
+                 light_weights,
+                 FT_LCD_FILTER_FIVE_TAPS );
+      library->lcd_filter_func = ft_lcd_filter_fir;
       library->lcd_extra       = 2;
       break;
 
@@ -356,6 +359,17 @@
 
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
+  FT_BASE( void )
+  ft_lcd_filter_fir( FT_Bitmap*           bitmap,
+                     FT_Render_Mode       mode,
+                     FT_LcdFiveTapFilter  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 c2ab2d1..5be56a1 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2424,6 +2424,10 @@
       internal->transform_delta.y = 0;
 
       internal->refcount = 1;
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+      ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS );
+#endif
     }
 
     if ( aface )
@@ -3607,8 +3611,31 @@
 
     for ( ; num_properties > 0; num_properties-- )
     {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
+      if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS )
+      {
+#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 );
+        }
+#else
+        error = FT_THROW( Unimplemented_Feature );
+        goto Exit;
+#endif
+      }
+      else
+      {
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
 
       if ( error )
         break;
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index c9292df..435854e 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -122,6 +122,60 @@
     FT_Bool  have_outline_shifted = FALSE;
     FT_Bool  have_buffer          = FALSE;
 
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+    FT_Int                   lcd_extra          = 0;
+    FT_LcdFiveTapFilter      lcd_weights        = { 0 };
+    FT_Bool                  have_custom_weight = FALSE;
+    FT_Bitmap_LcdFilterFunc  lcd_filter_func    = NULL;
+
+
+    if ( slot->face )
+    {
+      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 that needs 2 extra pixels.
+       */
+      ft_memcpy( lcd_weights,
+                 slot->face->internal->lcd_weights,
+                 FT_LCD_FILTER_FIVE_TAPS );
+      lcd_filter_func = ft_lcd_filter_fir;
+      lcd_extra       = 2;
+    }
+    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_filter_func = slot->library->lcd_filter_func;
+      lcd_extra       = slot->library->lcd_extra;
+    }
+
+#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
@@ -177,28 +231,23 @@
       height *= 3;
 
 #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;
       }
     }
-
 #endif
 
     /*
@@ -299,8 +348,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 */
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]