[Fontconfig] [PATCH 1/1] Add lcdfiltercustom option: controls the filter individual weights

Eric Rannaud eric.rannaud at gmail.com
Mon Nov 21 00:28:28 PST 2011

From: Eric Rannaud <e at nanocritical.com>

When lcdfilter is set to "lcdcustom", use lcdfiltercustom to retrieve a
string containing a space-separated list of double values between 0.0
and 1.0 and configure the renderer LCD filter (e.g. for freetype2, this
is done with FT_Library_SetLcdFilterWeights()).

If lcdfiltercustom is empty or is malformed, fontconfig users should
fallback to lcddefault.

With freetype2 as renderer, when fontconfig's FC_LCD_DEFAULT is mapped
to freetype2's FT_LCD_FILTER_DEFAULT, the configuration

  <match target="font">
    <edit mode="assign" name="lcdfilter">

corresponds to setting

  <match target="font">
    <edit mode="assign" name="lcdfilter">
  <match target="font">
    <edit mode="assign" name="lcdfiltercustom">
      <string>.0625 .25 .4375 .25 .0625</string>


Freetype2 has FT_Library_SetLcdFilterWeights() to control the configuration of
the filter used for LCD antialiasing. This gives more control than
FT_LCD_FILTER_DEFAULT, _LIGHT, _LEGACY, ... For instance, with:

  static const FT_Byte heavy_filter[5] = { 0x40, 0x80, 0x90, 0x80, 0x40 };

fonts are rendered bolder (see http://goo.gl/YHpNs, on the right is lcddefault).
Some users with poor eyesight will want to tweak this setting to make fonts more
readable, especially on low-res screens (e.g. a 24" 1920x1200 screen).

Fontconfig has an option to control the LCD AA filter, but only via a few
predefined values: lcdfilter can be set to lcdnone, lcddefault, lcdlight, or
lcdlegacy. However, other configurations for this filter are reasonable (e.g.
the one above, or those listed in http://www.infinality.net/files/infinality-settings).

This patch adds a fontconfig option to control the LCD filter directly.

For reference, see the freetype-devel discussion at

A few questions:

- Is a string the best way to set a list of values with fontconfig?

- Should we prefer values between 0 and 1000 instead of Double between 0 and 1?
  Note that in freetype2, the filter is actually using 5 uint8_t values between
  0 and 255 so rounding errors will affect the actual values used.

- Would you prefer a unique "lcdheavy" value for lcdfilter, corresponding to a new
  FT_LCD_FILTER_HEAVY in freetype2 for some fixed, and somewhat arbitrary,
  LCD filter configuration? The freetype2 developers are open to the idea, but I
  think we would all prefer complete control over the filter values.

I will have patches for Cairo and Xft to have them honor the new config option,
parse the list of filter values, and call FT_Library_SetLcdFilterWeights(). Any
other major users of fontconfig I should write patches for and submit upstream?


 doc/fontconfig-user.sgml |    5 +++++
 fontconfig/fontconfig.h  |    2 ++
 src/fcname.c             |    4 +++-
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index 217feb9..d0944ba 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -122,6 +122,10 @@ convenience for the applications' rendering mechanism.
   rgba            Int     unknown, rgb, bgr, vrgb, vbgr,
                           none - subpixel geometry
   lcdfilter       Int     Type of LCD filter
+  lcdfiltercustom String  Weights for the custom LCD filter, enabled by setting
+                          lcdfilter to lcdcustom. Example: with freetype2 as
+			  renderer, ".0625 .25 .4375 .25 .0625" corresponds to
+			  setting the option lcdfilter to lcddefault.
   minspace        Bool    Eliminate leading from line spacing
   charset         CharSet Unicode chars encoded by the font
   lang            String  List of RFC-3066-style languages this
@@ -494,6 +498,7 @@ symbolic names for common font values:
   lcddefault      lcdfilter       1
   lcdlight        lcdfilter       2
   lcdlegacy       lcdfilter       3
+  lcdcustom       lcdfilter       4
   hintnone        hintstyle       0
   hintslight      hintstyle       1
   hintmedium      hintstyle       2
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index db26b97..f05f570 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -111,6 +111,7 @@ typedef int		FcBool;
 #define FC_EMBEDDED_BITMAP  "embeddedbitmap"	/* Bool - true to enable embedded bitmaps */
 #define FC_DECORATIVE	    "decorative"	/* Bool - true if style is a decorative variant */
 #define FC_LCD_FILTER	    "lcdfilter"		/* Int */
+#define FC_LCD_FILTER_CUSTOM "lcdfiltercustom"	/* String. Space separated list of double */
 #define FC_CACHE_SUFFIX		    ".cache-"FC_CACHE_VERSION
 #define FC_DIR_CACHE_FILE	    "fonts.cache-"FC_CACHE_VERSION
@@ -177,6 +178,7 @@ typedef int		FcBool;
 #define FC_LCD_DEFAULT	    1
 #define FC_LCD_LIGHT	    2
 #define FC_LCD_LEGACY	    3
+#define FC_LCD_CUSTOM	    4
 typedef enum _FcType {
diff --git a/src/fcname.c b/src/fcname.c
index d77eff6..0697d10 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -75,7 +75,8 @@ static const FcObjectType _FcBaseObjectTypes[] = {
     { FC_EMBOLDEN,	FcTypeBool },
     { FC_EMBEDDED_BITMAP,   FcTypeBool },
     { FC_DECORATIVE,	FcTypeBool },
-    { FC_LCD_FILTER,	FcTypeInteger }, /* 41 */
+    { FC_LCD_FILTER,	FcTypeInteger },
+    { FC_LCD_FILTER_CUSTOM,    FcTypeString }, /* 42 */
 #define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
@@ -454,6 +455,7 @@ static const FcConstant _FcBaseConstants[] = {
     { (FcChar8 *) "lcddefault",	    "lcdfilter",    FC_LCD_DEFAULT },
     { (FcChar8 *) "lcdlight",	    "lcdfilter",    FC_LCD_LIGHT },
     { (FcChar8 *) "lcdlegacy",	    "lcdfilter",    FC_LCD_LEGACY },
+    { (FcChar8 *) "lcdcustom",      "lcdfilter",    FC_LCD_CUSTOM },
 #define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])

More information about the Fontconfig mailing list