[cairo] public API for setting the lcd filter type on cairo_font_option_t

Sylvain Pasche sylvain.pasche at gmail.com
Wed Jan 16 11:25:40 PST 2008


I'm writing this mail from a discussion about the lcd filter type on irc 
with Behdad and others.

The LCD filtering patch currently available in bugzilla which was 
written by David Turner and then modified by Debian maintainers uses the 
following internal API:

  /**
  * _cairo_font_options_set_lcd_filter:
  * @options: a #cairo_font_options_t
  * @lcd_filter: the new lcd filterorder
  *
  * Sets the lcd filter for the font options object. The lcd filter
  * specifies how pixels are filtered when rendered with an antialiasing
  * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
  * #cairo_lcd_filter_t for full details.
  **/
void
_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
				    cairo_lcd_filter_t    lcd_filter);


I don't think there's much to discuss for the prototype of the above 
function (outside of the comment).

cairo_lcd_filter_t is then defined using constants matching the Freetype 
ones:

/**
  * cairo_lcd_filter_t:
  * @CAIRO_LCD_FILTER_DEFAULT: Default LCD filter
  * @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
  * @CAIRO_LCD_FILTER_LIGHT: Variant lighter filter
  * @CAIRO_LCD_FILTER_LEGACY: Use the legacy LCD filter
  *
  * The LCD filter specifies the low-pass filter applied to LCD-optimized
  * bitmaps generated with an antialiasing mode of 
%CAIRO_ANTIALIAS_SUBPIXEL.
  **/
typedef enum _cairo_lcd_filter {
     CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_LCD_FILTER_NONE,
     CAIRO_LCD_FILTER_LIGHT,
     CAIRO_LCD_FILTER_LEGACY
} cairo_lcd_filter_t;


With a mapping:
     CAIRO_LCD_FILTER_DEFAULT => FT_LCD_FILTER_NONE
     CAIRO_LCD_FILTER_NONE => FT_LCD_FILTER_DEFAULT
     CAIRO_LCD_FILTER_LIGHT => FT_LCD_FILTER_LIGHT
     CAIRO_LCD_FILTER_LEGACY => FT_LCD_FILTER_LEGACY

Two issues with this enum:

* Cairo has a convention of having a constant CAIRO_XXX_DEFAULT to use 
the target device default setting. This above constant has a different 
meaning than this convention so another name has to be used for mapping 
to FT_LCD_FILTER_DEFAULT

* quoting Behdad: "... and LEGACY have no place in cairo as enum names"


Some information how the filtering is computed can be helpful when 
choosing a name.
FT_LCD_FILTER_NONE
*     Do not perform filtering.  When used with subpixel rendering, this
*     results in sometimes severe color fringes.

As expected this filter does nothing

FT_LCD_FILTER_DEFAULT
*    The default filter reduces color fringes considerably, at the cost
*    of a slight blurriness in the output.

FT_LCD_FILTER_LIGHT
*    The light filter is a variant that produces less blurriness at the
*    cost of slightly more color fringes than the default one.  It might
*    be better, depending on taste, your monitor, or your personal vision.

These two filters are using the _ft_lcd_filter_fir filter function in 
http://cvs.savannah.gnu.org/viewvc/freetype/freetype2/src/base/ftlcdfil.c?view=markup 
with different filter values:

static const FT_Byte  light_filter[5] =
                          { 0, 85, 86, 85, 0 };
/* the values here sum up to a value larger than 256, */
/* providing a cheap gamma correction                 */
static const FT_Byte  default_filter[5] =
                          { 0x10, 0x40, 0x70, 0x40, 0x10 };

The algorithm used in that filter function is FIR.


FT_LCD_FILTER_LEGACY
*     This filter corresponds to the original libXft color filter.  It
*     provides high contrast output but can exhibit really bad color
*     fringes if glyphs are not extremely well hinted to the pixel grid.
*     In other words, it only works well if the TrueType bytecode
*     interpreter is enabled *and* high-quality hinted fonts are used.
*
*     This filter is only provided for comparison purposes, and might be
*     disabled or stay unsupported in the future.

Quoting Keith: it's an intra-pixel filter, which means the three 
components have different curves; green gets a three-element gaussian, 
while r and b get sloping filters to left and right.


So each of these options uses a given algorithm with specific parameters 
modifying how the algorithm behaves.

 From quick googling, the Windows and ATSUI backends don't seem to offer 
per font lcd filtering options (ClearType appears to use global registry 
settings for controlling the filtering settings). So this would only be 
used by Freetype for now, which uses 4 types of filtering.

Some proposals, in the cairo default, none, default, light, legacy order:

algorithm + algorithm option:
     CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_LCD_FILTER_NONE,
     CAIRO_LCD_FILTER_FIR_NORMAL,
     CAIRO_LCD_FILTER_FIR_LIGHT,
     CAIRO_LCD_FILTER_INTRA_PIXEL

freetype centric, adapted (replacing default by normal):
     CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_LCD_FILTER_NONE,
     CAIRO_LCD_FILTER_NORMAL,
     CAIRO_LCD_FILTER_LIGHT,
     CAIRO_LCD_FILTER_LEGACY

Code author based naming (Carl's idea ;-) ):
     CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_LCD_FILTER_NONE,
     CAIRO_LCD_FILTER_DAVID,
     CAIRO_LCD_FILTER_DAVID_LIGHT,
     CAIRO_LCD_FILTER_KEITH


I hope this gives enough information start the discussion.

Sylvain



More information about the cairo mailing list