mozilla-cairo-lcd.patch
branchmozilla-1.9.2
changeset 118 deb8fdcf4792
child 237 676030198746
equal deleted inserted replaced
116:7039579bfd97 118:deb8fdcf4792
       
     1 # HG changeset patch
       
     2 # Parent 863b8585016fffd4755445eca723011717f4b930
       
     3 Subject: Add a Cairo LCD filter to use FreeType LCD colour filtering features
       
     4 References:
       
     5 https://bugzilla.mozilla.org/show_bug.cgi?id=404637
       
     6 http://bugs.freedesktop.org/show_bug.cgi?id=10301
       
     7 
       
     8 diff --git a/config/system-headers b/config/system-headers
       
     9 --- a/config/system-headers
       
    10 +++ b/config/system-headers
       
    11 @@ -262,16 +262,17 @@ Font.h
       
    12  Fonts.h
       
    13  fp.h
       
    14  fpieee.h
       
    15  frame/log.h
       
    16  frame/req.h
       
    17  freetype/freetype.h
       
    18  freetype/ftcache.h
       
    19  freetype/ftglyph.h
       
    20 +freetype/ftlcdfil.h
       
    21  freetype/ftsynth.h
       
    22  freetype/ftoutln.h
       
    23  freetype/ttnameid.h
       
    24  freetype/tttables.h
       
    25  freetype/t1tables.h
       
    26  fribidi/fribidi.h
       
    27  FSp_fopen.h
       
    28  fstream.h
       
    29 diff --git a/gfx/cairo/cairo/src/cairo-font-options.c b/gfx/cairo/cairo/src/cairo-font-options.c
       
    30 --- a/gfx/cairo/cairo/src/cairo-font-options.c
       
    31 +++ b/gfx/cairo/cairo/src/cairo-font-options.c
       
    32 @@ -34,41 +34,44 @@
       
    33   *      Owen Taylor <otaylor@redhat.com>
       
    34   */
       
    35  
       
    36  #include "cairoint.h"
       
    37  
       
    38  static const cairo_font_options_t _cairo_font_options_nil = {
       
    39      CAIRO_ANTIALIAS_DEFAULT,
       
    40      CAIRO_SUBPIXEL_ORDER_DEFAULT,
       
    41 +    CAIRO_LCD_FILTER_DEFAULT,
       
    42      CAIRO_HINT_STYLE_DEFAULT,
       
    43      CAIRO_HINT_METRICS_DEFAULT
       
    44  };
       
    45  
       
    46  /**
       
    47   * _cairo_font_options_init_default:
       
    48   * @options: a #cairo_font_options_t
       
    49   *
       
    50   * Initializes all fields of the font options object to default values.
       
    51   **/
       
    52  void
       
    53  _cairo_font_options_init_default (cairo_font_options_t *options)
       
    54  {
       
    55      options->antialias = CAIRO_ANTIALIAS_DEFAULT;
       
    56      options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
       
    57 +    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
       
    58      options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
       
    59      options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
       
    60  }
       
    61  
       
    62  void
       
    63  _cairo_font_options_init_copy (cairo_font_options_t		*options,
       
    64  			       const cairo_font_options_t	*other)
       
    65  {
       
    66      options->antialias = other->antialias;
       
    67      options->subpixel_order = other->subpixel_order;
       
    68 +    options->lcd_filter = other->lcd_filter;
       
    69      options->hint_style = other->hint_style;
       
    70      options->hint_metrics = other->hint_metrics;
       
    71  }
       
    72  
       
    73  /**
       
    74   * cairo_font_options_create:
       
    75   *
       
    76   * Allocates a new font options object with all options initialized
       
    77 @@ -184,16 +187,18 @@ cairo_font_options_merge (cairo_font_opt
       
    78  
       
    79      if (cairo_font_options_status ((cairo_font_options_t *) other))
       
    80  	return;
       
    81  
       
    82      if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
       
    83  	options->antialias = other->antialias;
       
    84      if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
       
    85  	options->subpixel_order = other->subpixel_order;
       
    86 +    if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
       
    87 +	options->lcd_filter = other->lcd_filter;
       
    88      if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
       
    89  	options->hint_style = other->hint_style;
       
    90      if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
       
    91  	options->hint_metrics = other->hint_metrics;
       
    92  }
       
    93  slim_hidden_def (cairo_font_options_merge);
       
    94  
       
    95  /**
       
    96 @@ -216,16 +221,17 @@ cairo_font_options_equal (const cairo_fo
       
    97      if (cairo_font_options_status ((cairo_font_options_t *) other))
       
    98  	return FALSE;
       
    99  
       
   100      if (options == other)
       
   101  	return TRUE;
       
   102  
       
   103      return (options->antialias == other->antialias &&
       
   104  	    options->subpixel_order == other->subpixel_order &&
       
   105 +	    options->lcd_filter == other->lcd_filter &&
       
   106  	    options->hint_style == other->hint_style &&
       
   107  	    options->hint_metrics == other->hint_metrics);
       
   108  }
       
   109  slim_hidden_def (cairo_font_options_equal);
       
   110  
       
   111  /**
       
   112   * cairo_font_options_hash:
       
   113   * @options: a #cairo_font_options_t
       
   114 @@ -241,17 +247,18 @@ slim_hidden_def (cairo_font_options_equa
       
   115  unsigned long
       
   116  cairo_font_options_hash (const cairo_font_options_t *options)
       
   117  {
       
   118      if (cairo_font_options_status ((cairo_font_options_t *) options))
       
   119  	options = &_cairo_font_options_nil; /* force default values */
       
   120  
       
   121      return ((options->antialias) |
       
   122  	    (options->subpixel_order << 4) |
       
   123 -	    (options->hint_style << 8) |
       
   124 +	    (options->lcd_filter << 8) |
       
   125 +	    (options->hint_style << 12) |
       
   126  	    (options->hint_metrics << 16));
       
   127  }
       
   128  slim_hidden_def (cairo_font_options_hash);
       
   129  
       
   130  /**
       
   131   * cairo_font_options_set_antialias:
       
   132   * @options: a #cairo_font_options_t
       
   133   * @antialias: the new antialiasing mode
       
   134 @@ -323,16 +330,58 @@ cairo_font_options_get_subpixel_order (c
       
   135  {
       
   136      if (cairo_font_options_status ((cairo_font_options_t *) options))
       
   137  	return CAIRO_SUBPIXEL_ORDER_DEFAULT;
       
   138  
       
   139      return options->subpixel_order;
       
   140  }
       
   141  
       
   142  /**
       
   143 + * _cairo_font_options_set_lcd_filter:
       
   144 + * @options: a #cairo_font_options_t
       
   145 + * @lcd_filter: the new LCD filter
       
   146 + *
       
   147 + * Sets the LCD filter for the font options object. The LCD filter
       
   148 + * specifies how pixels are filtered when rendered with an antialiasing
       
   149 + * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
       
   150 + * #cairo_lcd_filter_t for full details.
       
   151 + *
       
   152 + * Since: 1.8
       
   153 + **/
       
   154 +void
       
   155 +_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
       
   156 +				    cairo_lcd_filter_t    lcd_filter)
       
   157 +{
       
   158 +    if (cairo_font_options_status (options))
       
   159 +	return;
       
   160 +
       
   161 +    options->lcd_filter = lcd_filter;
       
   162 +}
       
   163 +
       
   164 +/**
       
   165 + * _cairo_font_options_get_lcd_filter:
       
   166 + * @options: a #cairo_font_options_t
       
   167 + *
       
   168 + * Gets the LCD filter for the font options object.
       
   169 + * See the documentation for #cairo_lcd_filter_t for full details.
       
   170 + *
       
   171 + * Return value: the LCD filter for the font options object
       
   172 + *
       
   173 + * Since: 1.8
       
   174 + **/
       
   175 +cairo_lcd_filter_t
       
   176 +_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
       
   177 +{
       
   178 +    if (cairo_font_options_status ((cairo_font_options_t *) options))
       
   179 +	return CAIRO_LCD_FILTER_DEFAULT;
       
   180 +
       
   181 +    return options->lcd_filter;
       
   182 +}
       
   183 +
       
   184 +/**
       
   185   * cairo_font_options_set_hint_style:
       
   186   * @options: a #cairo_font_options_t
       
   187   * @hint_style: the new hint style
       
   188   *
       
   189   * Sets the hint style for font outlines for the font options object.
       
   190   * This controls whether to fit font outlines to the pixel grid,
       
   191   * and if so, whether to optimize for fidelity or contrast.
       
   192   * See the documentation for #cairo_hint_style_t for full details.
       
   193 diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c
       
   194 --- a/gfx/cairo/cairo/src/cairo-ft-font.c
       
   195 +++ b/gfx/cairo/cairo/src/cairo-ft-font.c
       
   196 @@ -54,16 +54,38 @@
       
   197  #include FT_FREETYPE_H
       
   198  #include FT_OUTLINE_H
       
   199  #include FT_IMAGE_H
       
   200  #include FT_TRUETYPE_TABLES_H
       
   201  #if HAVE_FT_GLYPHSLOT_EMBOLDEN
       
   202  #include FT_SYNTHESIS_H
       
   203  #endif
       
   204  
       
   205 +#include FT_LCD_FILTER_H
       
   206 +
       
   207 +/* Fontconfig version older than 2.6 didn't have these options */
       
   208 +#ifndef FC_LCD_FILTER
       
   209 +#define FC_LCD_FILTER	"lcdfilter"
       
   210 +#endif
       
   211 +/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
       
   212 +#ifndef FC_LCD_NONE
       
   213 +#define FC_LCD_NONE	0
       
   214 +#define FC_LCD_DEFAULT	1
       
   215 +#define FC_LCD_LIGHT	2
       
   216 +#define FC_LCD_LEGACY	3
       
   217 +#endif
       
   218 +
       
   219 +/* FreeType version older than 2.3.5(?) didn't have these options */
       
   220 +#ifndef FT_LCD_FILTER_NONE
       
   221 +#define FT_LCD_FILTER_NONE	0
       
   222 +#define FT_LCD_FILTER_DEFAULT	1
       
   223 +#define FT_LCD_FILTER_LIGHT	2
       
   224 +#define FT_LCD_FILTER_LEGACY	16
       
   225 +#endif
       
   226 +
       
   227  #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
       
   228  #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
       
   229  #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
       
   230  #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
       
   231  
       
   232  /* This is the max number of FT_face objects we keep open at once
       
   233   */
       
   234  #define MAX_OPEN_FACES 10
       
   235 @@ -772,46 +794,309 @@ _cairo_ft_unscaled_font_set_scale (cairo
       
   236  					unscaled->face->available_sizes[best_i].height);
       
   237  	if (error)
       
   238  	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   239      }
       
   240  
       
   241      return CAIRO_STATUS_SUCCESS;
       
   242  }
       
   243  
       
   244 -/* Empirically-derived subpixel filtering values thanks to Keith
       
   245 - * Packard and libXft. */
       
   246 -static const int    filters[3][3] = {
       
   247 -    /* red */
       
   248 -#if 0
       
   249 -    {    65538*4/7,65538*2/7,65538*1/7 },
       
   250 -    /* green */
       
   251 -    {    65536*1/4, 65536*2/4, 65537*1/4 },
       
   252 -    /* blue */
       
   253 -    {    65538*1/7,65538*2/7,65538*4/7 },
       
   254 +/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
       
   255 + * into a different format. For example, we want to convert a
       
   256 + * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
       
   257 + * ARGB or ABGR bitmap.
       
   258 + *
       
   259 + * this function prepares a target descriptor for this operation.
       
   260 + *
       
   261 + * input :: target bitmap descriptor. The function will set its
       
   262 + *          'width', 'rows' and 'pitch' fields, and only these
       
   263 + *
       
   264 + * slot  :: the glyph slot containing the source bitmap. this
       
   265 + *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
       
   266 + *
       
   267 + * mode  :: the requested final rendering mode. supported values are
       
   268 + *          MONO, NORMAL (i.e. gray), LCD and LCD_V
       
   269 + *
       
   270 + * the function returns the size in bytes of the corresponding buffer,
       
   271 + * it's up to the caller to allocate the corresponding memory block
       
   272 + * before calling _fill_xrender_bitmap
       
   273 + *
       
   274 + * it also returns -1 in case of error (e.g. incompatible arguments,
       
   275 + * like trying to convert a gray bitmap into a monochrome one)
       
   276 + */
       
   277 +static int
       
   278 +_compute_xrender_bitmap_size(FT_Bitmap      *target,
       
   279 +			     FT_GlyphSlot    slot,
       
   280 +			     FT_Render_Mode  mode)
       
   281 +{
       
   282 +    FT_Bitmap *ftbit;
       
   283 +    int width, height, pitch;
       
   284 +
       
   285 +    if (slot->format != FT_GLYPH_FORMAT_BITMAP)
       
   286 +	return -1;
       
   287 +
       
   288 +    /* compute the size of the final bitmap */
       
   289 +    ftbit = &slot->bitmap;
       
   290 +
       
   291 +    width = ftbit->width;
       
   292 +    height = ftbit->rows;
       
   293 +    pitch = (width + 3) & ~3;
       
   294 +
       
   295 +    switch (ftbit->pixel_mode) {
       
   296 +    case FT_PIXEL_MODE_MONO:
       
   297 +	if (mode == FT_RENDER_MODE_MONO) {
       
   298 +	    pitch = (((width + 31) & ~31) >> 3);
       
   299 +	    break;
       
   300 +	}
       
   301 +	/* fall-through */
       
   302 +
       
   303 +    case FT_PIXEL_MODE_GRAY:
       
   304 +	if (mode == FT_RENDER_MODE_LCD ||
       
   305 +	    mode == FT_RENDER_MODE_LCD_V)
       
   306 +	{
       
   307 +	    /* each pixel is replicated into a 32-bit ARGB value */
       
   308 +	    pitch = width * 4;
       
   309 +	}
       
   310 +	break;
       
   311 +
       
   312 +    case FT_PIXEL_MODE_LCD:
       
   313 +	if (mode != FT_RENDER_MODE_LCD)
       
   314 +	    return -1;
       
   315 +
       
   316 +	/* horz pixel triplets are packed into 32-bit ARGB values */
       
   317 +	width /= 3;
       
   318 +	pitch = width * 4;
       
   319 +	break;
       
   320 +
       
   321 +    case FT_PIXEL_MODE_LCD_V:
       
   322 +	if (mode != FT_RENDER_MODE_LCD_V)
       
   323 +	    return -1;
       
   324 +
       
   325 +	/* vert pixel triplets are packed into 32-bit ARGB values */
       
   326 +	height /= 3;
       
   327 +	pitch = width * 4;
       
   328 +	break;
       
   329 +
       
   330 +    default:  /* unsupported source format */
       
   331 +	return -1;
       
   332 +    }
       
   333 +
       
   334 +    target->width = width;
       
   335 +    target->rows = height;
       
   336 +    target->pitch = pitch;
       
   337 +    target->buffer = NULL;
       
   338 +
       
   339 +    return pitch * height;
       
   340 +}
       
   341 +
       
   342 +/* this functions converts the glyph bitmap found in a FT_GlyphSlot
       
   343 + * into a different format (see _compute_xrender_bitmap_size)
       
   344 + *
       
   345 + * you should call this function after _compute_xrender_bitmap_size
       
   346 + *
       
   347 + * target :: target bitmap descriptor. Note that its 'buffer' pointer
       
   348 + *           must point to memory allocated by the caller
       
   349 + *
       
   350 + * slot   :: the glyph slot containing the source bitmap
       
   351 + *
       
   352 + * mode   :: the requested final rendering mode
       
   353 + *
       
   354 + * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
       
   355 + */
       
   356 +static void
       
   357 +_fill_xrender_bitmap(FT_Bitmap      *target,
       
   358 +		     FT_GlyphSlot    slot,
       
   359 +		     FT_Render_Mode  mode,
       
   360 +		     int             bgr)
       
   361 +{
       
   362 +    FT_Bitmap *ftbit = &slot->bitmap;
       
   363 +    unsigned char *srcLine = ftbit->buffer;
       
   364 +    unsigned char *dstLine = target->buffer;
       
   365 +    int src_pitch = ftbit->pitch;
       
   366 +    int width = target->width;
       
   367 +    int height = target->rows;
       
   368 +    int pitch = target->pitch;
       
   369 +    int subpixel;
       
   370 +    int h;
       
   371 +
       
   372 +    subpixel = (mode == FT_RENDER_MODE_LCD ||
       
   373 +		mode == FT_RENDER_MODE_LCD_V);
       
   374 +
       
   375 +    if (src_pitch < 0)
       
   376 +	srcLine -= src_pitch * (ftbit->rows - 1);
       
   377 +
       
   378 +    target->pixel_mode = ftbit->pixel_mode;
       
   379 +
       
   380 +    switch (ftbit->pixel_mode) {
       
   381 +    case FT_PIXEL_MODE_MONO:
       
   382 +	if (subpixel) {
       
   383 +	    /* convert mono to ARGB32 values */
       
   384 +
       
   385 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
       
   386 +		int x;
       
   387 +
       
   388 +		for (x = 0; x < width; x++) {
       
   389 +		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
       
   390 +			((unsigned int *) dstLine)[x] = 0xffffffffU;
       
   391 +		}
       
   392 +	    }
       
   393 +	    target->pixel_mode = FT_PIXEL_MODE_LCD;
       
   394 +
       
   395 +	} else if (mode == FT_RENDER_MODE_NORMAL) {
       
   396 +	    /* convert mono to 8-bit gray */
       
   397 +
       
   398 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
       
   399 +		int x;
       
   400 +
       
   401 +		for (x = 0; x < width; x++) {
       
   402 +		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
       
   403 +			dstLine[x] = 0xff;
       
   404 +		}
       
   405 +	    }
       
   406 +	    target->pixel_mode = FT_PIXEL_MODE_GRAY;
       
   407 +
       
   408 +	} else {
       
   409 +	    /* copy mono to mono */
       
   410 +
       
   411 +	    int  bytes = (width + 7) >> 3;
       
   412 +
       
   413 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
       
   414 +		memcpy (dstLine, srcLine, bytes);
       
   415 +	}
       
   416 +	break;
       
   417 +
       
   418 +    case FT_PIXEL_MODE_GRAY:
       
   419 +	if (subpixel) {
       
   420 +	    /* convert gray to ARGB32 values */
       
   421 +
       
   422 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
       
   423 +		int x;
       
   424 +		unsigned int *dst = (unsigned int *) dstLine;
       
   425 +
       
   426 +		for (x = 0; x < width; x++) {
       
   427 +		    unsigned int pix = srcLine[x];
       
   428 +
       
   429 +		    pix |= (pix << 8);
       
   430 +		    pix |= (pix << 16);
       
   431 +
       
   432 +		    dst[x] = pix;
       
   433 +		}
       
   434 +	    }
       
   435 +	    target->pixel_mode = FT_PIXEL_MODE_LCD;
       
   436 +        } else {
       
   437 +            /* copy gray into gray */
       
   438 +
       
   439 +            for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
       
   440 +                memcpy (dstLine, srcLine, width);
       
   441 +        }
       
   442 +        break;
       
   443 +
       
   444 +    case FT_PIXEL_MODE_LCD:
       
   445 +	if (!bgr) {
       
   446 +	    /* convert horizontal RGB into ARGB32 */
       
   447 +
       
   448 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
       
   449 +		int x;
       
   450 +		unsigned char *src = srcLine;
       
   451 +		unsigned int *dst = (unsigned int *) dstLine;
       
   452 +
       
   453 +		for (x = 0; x < width; x++, src += 3) {
       
   454 +		    unsigned int  pix;
       
   455 +
       
   456 +		    pix = ((unsigned int)src[0] << 16) |
       
   457 +			  ((unsigned int)src[1] <<  8) |
       
   458 +			  ((unsigned int)src[2]      ) |
       
   459 +			  ((unsigned int)src[1] << 24) ;
       
   460 +
       
   461 +		    dst[x] = pix;
       
   462 +		}
       
   463 +	    }
       
   464 +	} else {
       
   465 +	    /* convert horizontal BGR into ARGB32 */
       
   466 +
       
   467 +	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
       
   468 +
       
   469 +		int x;
       
   470 +		unsigned char *src = srcLine;
       
   471 +		unsigned int *dst = (unsigned int *) dstLine;
       
   472 +
       
   473 +		for (x = 0; x < width; x++, src += 3) {
       
   474 +		    unsigned int  pix;
       
   475 +
       
   476 +		    pix = ((unsigned int)src[2] << 16) |
       
   477 +			  ((unsigned int)src[1] <<  8) |
       
   478 +			  ((unsigned int)src[0]      ) |
       
   479 +			  ((unsigned int)src[1] << 24) ;
       
   480 +
       
   481 +		    dst[x] = pix;
       
   482 +		}
       
   483 +	    }
       
   484 +	}
       
   485 +	break;
       
   486 +
       
   487 +    default:  /* FT_PIXEL_MODE_LCD_V */
       
   488 +	/* convert vertical RGB into ARGB32 */
       
   489 +	if (!bgr) {
       
   490 +
       
   491 +	    for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
       
   492 +		int x;
       
   493 +		unsigned char* src = srcLine;
       
   494 +		unsigned int*  dst = (unsigned int *) dstLine;
       
   495 +
       
   496 +		for (x = 0; x < width; x++, src += 1) {
       
   497 +		    unsigned int pix;
       
   498 +#if 1
       
   499 +		    pix = ((unsigned int)src[0]           << 16) |
       
   500 +			  ((unsigned int)src[src_pitch]   <<  8) |
       
   501 +			  ((unsigned int)src[src_pitch*2]      ) |
       
   502 +			  0xFF000000 ;
       
   503 +#else
       
   504 +		    pix = ((unsigned int)src[0]           << 16) |
       
   505 +			  ((unsigned int)src[src_pitch]   <<  8) |
       
   506 +			  ((unsigned int)src[src_pitch*2]      ) |
       
   507 +			  ((unsigned int)src[src_pitch]   << 24) ;
       
   508  #endif
       
   509 -    {    65538*9/13,65538*3/13,65538*1/13 },
       
   510 -    /* green */
       
   511 -    {    65538*1/6, 65538*4/6, 65538*1/6 },
       
   512 -    /* blue */
       
   513 -    {    65538*1/13,65538*3/13,65538*9/13 },
       
   514 -};
       
   515 +		    dst[x] = pix;
       
   516 +		}
       
   517 +	    }
       
   518 +	} else {
       
   519 +
       
   520 +	    for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
       
   521 +		int x;
       
   522 +		unsigned char *src = srcLine;
       
   523 +		unsigned int *dst = (unsigned int *) dstLine;
       
   524 +
       
   525 +		for (x = 0; x < width; x++, src += 1) {
       
   526 +		    unsigned int  pix;
       
   527 +
       
   528 +		    pix = ((unsigned int)src[src_pitch * 2] << 16) |
       
   529 +			  ((unsigned int)src[src_pitch]     <<  8) |
       
   530 +			  ((unsigned int)src[0]                  ) |
       
   531 +			  ((unsigned int)src[src_pitch]     << 24) ;
       
   532 +
       
   533 +		    dst[x] = pix;
       
   534 +		}
       
   535 +	    }
       
   536 +	}
       
   537 +    }
       
   538 +}
       
   539 +
       
   540  
       
   541  /* Fills in val->image with an image surface created from @bitmap
       
   542   */
       
   543  static cairo_status_t
       
   544  _get_bitmap_surface (FT_Bitmap		     *bitmap,
       
   545  		     cairo_bool_t	      own_buffer,
       
   546  		     cairo_font_options_t    *font_options,
       
   547  		     cairo_image_surface_t  **surface)
       
   548  {
       
   549      int width, height, stride;
       
   550      unsigned char *data;
       
   551      int format = CAIRO_FORMAT_A8;
       
   552 -    cairo_bool_t subpixel = FALSE;
       
   553 +    cairo_image_surface_t *image;
       
   554  
       
   555      width = bitmap->width;
       
   556      height = bitmap->rows;
       
   557  
       
   558      if (width == 0 || height == 0) {
       
   559  	*surface = (cairo_image_surface_t *)
       
   560  	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
       
   561  	return (*surface)->base.status;
       
   562 @@ -858,154 +1143,63 @@ _get_bitmap_surface (FT_Bitmap		     *bi
       
   563  	}
       
   564  #endif
       
   565  	format = CAIRO_FORMAT_A1;
       
   566  	break;
       
   567  
       
   568      case FT_PIXEL_MODE_LCD:
       
   569      case FT_PIXEL_MODE_LCD_V:
       
   570      case FT_PIXEL_MODE_GRAY:
       
   571 -	switch (font_options->antialias) {
       
   572 -	case CAIRO_ANTIALIAS_DEFAULT:
       
   573 -	case CAIRO_ANTIALIAS_GRAY:
       
   574 -	case CAIRO_ANTIALIAS_NONE:
       
   575 -	default:
       
   576 +        if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
       
   577  	    stride = bitmap->pitch;
       
   578  	    if (own_buffer) {
       
   579  		data = bitmap->buffer;
       
   580  	    } else {
       
   581  		data = _cairo_malloc_ab (height, stride);
       
   582  		if (!data)
       
   583  		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   584  
       
   585  		memcpy (data, bitmap->buffer, stride * height);
       
   586  	    }
       
   587  	    format = CAIRO_FORMAT_A8;
       
   588 -	    break;
       
   589 -	case CAIRO_ANTIALIAS_SUBPIXEL: {
       
   590 -	    int		    x, y;
       
   591 -	    unsigned char   *in_line, *out_line, *in;
       
   592 -	    unsigned int    *out;
       
   593 -	    unsigned int    red, green, blue;
       
   594 -	    int		    rf, gf, bf;
       
   595 -	    int		    s;
       
   596 -	    int		    o, os;
       
   597 -	    unsigned char   *data_rgba;
       
   598 -	    unsigned int    width_rgba, stride_rgba;
       
   599 -	    int		    vmul = 1;
       
   600 -	    int		    hmul = 1;
       
   601 -
       
   602 -	    switch (font_options->subpixel_order) {
       
   603 -	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
       
   604 -	    case CAIRO_SUBPIXEL_ORDER_RGB:
       
   605 -	    case CAIRO_SUBPIXEL_ORDER_BGR:
       
   606 -	    default:
       
   607 -		width /= 3;
       
   608 -		hmul = 3;
       
   609 -		break;
       
   610 -	    case CAIRO_SUBPIXEL_ORDER_VRGB:
       
   611 -	    case CAIRO_SUBPIXEL_ORDER_VBGR:
       
   612 -		vmul = 3;
       
   613 -		height /= 3;
       
   614 -		break;
       
   615 -	    }
       
   616 -	    /*
       
   617 -	     * Filter the glyph to soften the color fringes
       
   618 -	     */
       
   619 -	    width_rgba = width;
       
   620 +	} else {
       
   621 +	    /* if we get there, the  data from the source bitmap
       
   622 +	     * really comes from _fill_xrender_bitmap, and is
       
   623 +	     * made of 32-bit ARGB or ABGR values */
       
   624 +	    assert (own_buffer != 0);
       
   625 +	    assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
       
   626 +
       
   627 +	    data = bitmap->buffer;
       
   628  	    stride = bitmap->pitch;
       
   629 -	    stride_rgba = (width_rgba * 4 + 3) & ~3;
       
   630 -	    data_rgba = calloc (stride_rgba, height);
       
   631 -	    if (unlikely (data_rgba == NULL)) {
       
   632 -		if (own_buffer)
       
   633 -		    free (bitmap->buffer);
       
   634 -		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   635 -	    }
       
   636 -
       
   637 -	    os = 1;
       
   638 -	    switch (font_options->subpixel_order) {
       
   639 -	    case CAIRO_SUBPIXEL_ORDER_VRGB:
       
   640 -		os = stride;
       
   641 -	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
       
   642 -	    case CAIRO_SUBPIXEL_ORDER_RGB:
       
   643 -	    default:
       
   644 -		rf = 0;
       
   645 -		gf = 1;
       
   646 -		bf = 2;
       
   647 -		break;
       
   648 -	    case CAIRO_SUBPIXEL_ORDER_VBGR:
       
   649 -		os = stride;
       
   650 -	    case CAIRO_SUBPIXEL_ORDER_BGR:
       
   651 -		bf = 0;
       
   652 -		gf = 1;
       
   653 -		rf = 2;
       
   654 -		break;
       
   655 -	    }
       
   656 -	    in_line = bitmap->buffer;
       
   657 -	    out_line = data_rgba;
       
   658 -	    for (y = 0; y < height; y++)
       
   659 -	    {
       
   660 -		in = in_line;
       
   661 -		out = (unsigned int *) out_line;
       
   662 -		in_line += stride * vmul;
       
   663 -		out_line += stride_rgba;
       
   664 -		for (x = 0; x < width * hmul; x += hmul)
       
   665 -		{
       
   666 -		    red = green = blue = 0;
       
   667 -		    o = 0;
       
   668 -		    for (s = 0; s < 3; s++)
       
   669 -		    {
       
   670 -			red += filters[rf][s]*in[x+o];
       
   671 -			green += filters[gf][s]*in[x+o];
       
   672 -			blue += filters[bf][s]*in[x+o];
       
   673 -			o += os;
       
   674 -		    }
       
   675 -		    red = red / 65536;
       
   676 -		    green = green / 65536;
       
   677 -		    blue = blue / 65536;
       
   678 -		    *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
       
   679 -		}
       
   680 -	    }
       
   681 -
       
   682 -	    /* Images here are stored in native format. The
       
   683 -	     * backend must convert to its own format as needed
       
   684 -	     */
       
   685 -
       
   686 -	    if (own_buffer)
       
   687 -		free (bitmap->buffer);
       
   688 -	    data = data_rgba;
       
   689 -	    stride = stride_rgba;
       
   690  	    format = CAIRO_FORMAT_ARGB32;
       
   691 -	    subpixel = TRUE;
       
   692 -	    break;
       
   693 -	}
       
   694  	}
       
   695  	break;
       
   696      case FT_PIXEL_MODE_GRAY2:
       
   697      case FT_PIXEL_MODE_GRAY4:
       
   698  	/* These could be triggered by very rare types of TrueType fonts */
       
   699      default:
       
   700  	if (own_buffer)
       
   701  	    free (bitmap->buffer);
       
   702  	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   703      }
       
   704  
       
   705 -    *surface = (cairo_image_surface_t *)
       
   706 +    /* XXX */
       
   707 +    *surface = image = (cairo_image_surface_t *)
       
   708  	cairo_image_surface_create_for_data (data,
       
   709  					     format,
       
   710  					     width, height, stride);
       
   711 -    if ((*surface)->base.status) {
       
   712 +    if (image->base.status) {
       
   713  	free (data);
       
   714  	return (*surface)->base.status;
       
   715      }
       
   716  
       
   717 -    if (subpixel)
       
   718 -	pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
       
   719 -
       
   720 -    _cairo_image_surface_assume_ownership_of_data ((*surface));
       
   721 +    if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
       
   722 +	pixman_image_set_component_alpha (image->pixman_image, TRUE);
       
   723 +
       
   724 +    _cairo_image_surface_assume_ownership_of_data (image);
       
   725  
       
   726      _cairo_debug_check_image_surface_is_defined (&(*surface)->base);
       
   727  
       
   728      return CAIRO_STATUS_SUCCESS;
       
   729  }
       
   730  
       
   731  /* Converts an outline FT_GlyphSlot into an image
       
   732   *
       
   733 @@ -1022,129 +1216,169 @@ _get_bitmap_surface (FT_Bitmap		     *bi
       
   734   * when we add subpixel support. If so, we may want to eliminate
       
   735   * this version of the code path entirely.
       
   736   */
       
   737  static cairo_status_t
       
   738  _render_glyph_outline (FT_Face                    face,
       
   739  		       cairo_font_options_t	 *font_options,
       
   740  		       cairo_image_surface_t	**surface)
       
   741  {
       
   742 +    int rgba = FC_RGBA_UNKNOWN;
       
   743 +    int lcd_filter = FT_LCD_FILTER_LEGACY;
       
   744      FT_GlyphSlot glyphslot = face->glyph;
       
   745      FT_Outline *outline = &glyphslot->outline;
       
   746      FT_Bitmap bitmap;
       
   747      FT_BBox cbox;
       
   748 -    FT_Matrix matrix;
       
   749 -    int hmul = 1;
       
   750 -    int vmul = 1;
       
   751 -    unsigned int width, height, stride;
       
   752 -    cairo_bool_t subpixel = FALSE;
       
   753 +    unsigned int width, height;
       
   754      cairo_status_t status;
       
   755 +    FT_Error fterror;
       
   756 +    FT_Library library = glyphslot->library;
       
   757 +    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
       
   758 +
       
   759 +    switch (font_options->antialias) {
       
   760 +    case CAIRO_ANTIALIAS_NONE:
       
   761 +	render_mode = FT_RENDER_MODE_MONO;
       
   762 +	break;
       
   763 +
       
   764 +    case CAIRO_ANTIALIAS_SUBPIXEL:
       
   765 +	switch (font_options->subpixel_order) {
       
   766 +	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
       
   767 +	    case CAIRO_SUBPIXEL_ORDER_RGB:
       
   768 +	    case CAIRO_SUBPIXEL_ORDER_BGR:
       
   769 +		render_mode = FT_RENDER_MODE_LCD;
       
   770 +		break;
       
   771 +
       
   772 +	    case CAIRO_SUBPIXEL_ORDER_VRGB:
       
   773 +	    case CAIRO_SUBPIXEL_ORDER_VBGR:
       
   774 +		render_mode = FT_RENDER_MODE_LCD_V;
       
   775 +		break;
       
   776 +	}
       
   777 +
       
   778 +	switch (font_options->lcd_filter) {
       
   779 +	case CAIRO_LCD_FILTER_NONE:
       
   780 +	    lcd_filter = FT_LCD_FILTER_NONE;
       
   781 +	    break;
       
   782 +	case CAIRO_LCD_FILTER_DEFAULT:
       
   783 +	case CAIRO_LCD_FILTER_INTRA_PIXEL:
       
   784 +	    lcd_filter = FT_LCD_FILTER_LEGACY;
       
   785 +	    break;
       
   786 +	case CAIRO_LCD_FILTER_FIR3:
       
   787 +	    lcd_filter = FT_LCD_FILTER_LIGHT;
       
   788 +	    break;
       
   789 +	case CAIRO_LCD_FILTER_FIR5:
       
   790 +	    lcd_filter = FT_LCD_FILTER_DEFAULT;
       
   791 +	    break;
       
   792 +	}
       
   793 +
       
   794 +	break;
       
   795 +
       
   796 +    case CAIRO_ANTIALIAS_DEFAULT:
       
   797 +    case CAIRO_ANTIALIAS_GRAY:
       
   798 +	render_mode = FT_RENDER_MODE_NORMAL;
       
   799 +    }
       
   800  
       
   801      FT_Outline_Get_CBox (outline, &cbox);
       
   802  
       
   803      cbox.xMin &= -64;
       
   804      cbox.yMin &= -64;
       
   805      cbox.xMax = (cbox.xMax + 63) & -64;
       
   806      cbox.yMax = (cbox.yMax + 63) & -64;
       
   807  
       
   808      width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
       
   809      height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
       
   810 -    stride = (width * hmul + 3) & ~3;
       
   811  
       
   812      if (width * height == 0) {
       
   813  	cairo_format_t format;
       
   814  	/* Looks like fb handles zero-sized images just fine */
       
   815 -	switch (font_options->antialias) {
       
   816 -	case CAIRO_ANTIALIAS_NONE:
       
   817 +	switch (render_mode) {
       
   818 +	case FT_RENDER_MODE_MONO:
       
   819  	    format = CAIRO_FORMAT_A1;
       
   820  	    break;
       
   821 -	case CAIRO_ANTIALIAS_SUBPIXEL:
       
   822 +	case FT_RENDER_MODE_LCD:
       
   823 +	case FT_RENDER_MODE_LCD_V:
       
   824  	    format= CAIRO_FORMAT_ARGB32;
       
   825  	    break;
       
   826 -	case CAIRO_ANTIALIAS_DEFAULT:
       
   827 -	case CAIRO_ANTIALIAS_GRAY:
       
   828 +	case FT_RENDER_MODE_LIGHT:
       
   829 +	case FT_RENDER_MODE_NORMAL:
       
   830 +	case FT_RENDER_MODE_MAX:
       
   831  	default:
       
   832  	    format = CAIRO_FORMAT_A8;
       
   833  	    break;
       
   834  	}
       
   835  
       
   836  	(*surface) = (cairo_image_surface_t *)
       
   837  	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
       
   838  	if ((*surface)->base.status)
       
   839  	    return (*surface)->base.status;
       
   840      } else  {
       
   841  
       
   842 -	matrix.xx = matrix.yy = 0x10000L;
       
   843 -	matrix.xy = matrix.yx = 0;
       
   844 -
       
   845 -	switch (font_options->antialias) {
       
   846 -	case CAIRO_ANTIALIAS_NONE:
       
   847 -	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
       
   848 -	    bitmap.num_grays  = 1;
       
   849 -	    stride = ((width + 31) & -32) >> 3;
       
   850 +	int bitmap_size;
       
   851 +
       
   852 +	switch (render_mode) {
       
   853 +	case FT_RENDER_MODE_LCD:
       
   854 +	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
       
   855 +		rgba = FC_RGBA_BGR;
       
   856 +	    } else {
       
   857 +		rgba = FC_RGBA_RGB;
       
   858 +	    }
       
   859  	    break;
       
   860 -	case CAIRO_ANTIALIAS_DEFAULT:
       
   861 -	case CAIRO_ANTIALIAS_GRAY:
       
   862 -	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
       
   863 -	    bitmap.num_grays  = 256;
       
   864 -	    stride = (width + 3) & -4;
       
   865 +	case FT_RENDER_MODE_LCD_V:
       
   866 +	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
       
   867 +		rgba = FC_RGBA_VBGR;
       
   868 +	    } else {
       
   869 +		rgba = FC_RGBA_VRGB;
       
   870 +	    }
       
   871  	    break;
       
   872 -	case CAIRO_ANTIALIAS_SUBPIXEL:
       
   873 -	    switch (font_options->subpixel_order) {
       
   874 -	    case CAIRO_SUBPIXEL_ORDER_RGB:
       
   875 -	    case CAIRO_SUBPIXEL_ORDER_BGR:
       
   876 -	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
       
   877 -	    default:
       
   878 -		matrix.xx *= 3;
       
   879 -		hmul = 3;
       
   880 -		subpixel = TRUE;
       
   881 -		break;
       
   882 -	    case CAIRO_SUBPIXEL_ORDER_VRGB:
       
   883 -	    case CAIRO_SUBPIXEL_ORDER_VBGR:
       
   884 -		matrix.yy *= 3;
       
   885 -		vmul = 3;
       
   886 -		subpixel = TRUE;
       
   887 -		break;
       
   888 -	    }
       
   889 -	    FT_Outline_Transform (outline, &matrix);
       
   890 -
       
   891 -	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
       
   892 -	    bitmap.num_grays  = 256;
       
   893 -	    stride = (width * hmul + 3) & -4;
       
   894 +	case FT_RENDER_MODE_MONO:
       
   895 +	case FT_RENDER_MODE_LIGHT:
       
   896 +	case FT_RENDER_MODE_NORMAL:
       
   897 +	case FT_RENDER_MODE_MAX:
       
   898 +	default:
       
   899 +	    break;
       
   900  	}
       
   901  
       
   902 -	bitmap.pitch = stride;
       
   903 -	bitmap.width = width * hmul;
       
   904 -	bitmap.rows = height * vmul;
       
   905 -	bitmap.buffer = calloc (stride, bitmap.rows);
       
   906 +	FT_Library_SetLcdFilter (library, lcd_filter);
       
   907 +
       
   908 +	fterror = FT_Render_Glyph (face->glyph, render_mode);
       
   909 +
       
   910 +	FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
       
   911 +
       
   912 +	if (fterror != 0)
       
   913 +	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   914 +
       
   915 +	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
       
   916 +						    face->glyph,
       
   917 +						    render_mode);
       
   918 +	if (bitmap_size < 0)
       
   919 +	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   920 +
       
   921 +	bitmap.buffer = calloc (1, bitmap_size);
       
   922  	if (unlikely (bitmap.buffer == NULL))
       
   923  	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   924  
       
   925 -	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
       
   926 -
       
   927 -	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
       
   928 -	    free (bitmap.buffer);
       
   929 -	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
   930 -	}
       
   931 -
       
   932 +	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
       
   933 +			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
       
   934 +
       
   935 +	/* Note:
       
   936 +	 * _get_bitmap_surface will free bitmap.buffer if there is an error
       
   937 +	 */
       
   938  	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
       
   939  	if (unlikely (status))
       
   940  	    return status;
       
   941 +
       
   942 +	/* Note: the font's coordinate system is upside down from ours, so the
       
   943 +	 * Y coordinate of the control box needs to be negated.  Moreover, device
       
   944 +	 * offsets are position of glyph origin relative to top left while xMin
       
   945 +	 * and yMax are offsets of top left relative to origin.  Another negation.
       
   946 +	 */
       
   947 +	cairo_surface_set_device_offset (&(*surface)->base,
       
   948 +					 (double)-glyphslot->bitmap_left,
       
   949 +					 (double)+glyphslot->bitmap_top);
       
   950      }
       
   951  
       
   952 -    /*
       
   953 -     * Note: the font's coordinate system is upside down from ours, so the
       
   954 -     * Y coordinate of the control box needs to be negated.  Moreover, device
       
   955 -     * offsets are position of glyph origin relative to top left while xMin
       
   956 -     * and yMax are offsets of top left relative to origin.  Another negation.
       
   957 -     */
       
   958 -    cairo_surface_set_device_offset (&(*surface)->base,
       
   959 -				     floor (-(double) cbox.xMin / 64.0),
       
   960 -				     floor (+(double) cbox.yMax / 64.0));
       
   961 -
       
   962      return CAIRO_STATUS_SUCCESS;
       
   963  }
       
   964  
       
   965  /* Converts a bitmap (or other) FT_GlyphSlot into an image */
       
   966  static cairo_status_t
       
   967  _render_glyph_bitmap (FT_Face		      face,
       
   968  		      cairo_font_options_t   *font_options,
       
   969  		      cairo_image_surface_t **surface)
       
   970 @@ -1354,16 +1588,17 @@ _get_pattern_ft_options (FcPattern *patt
       
   971  
       
   972      /* disable antialiasing if requested */
       
   973      if (FcPatternGetBool (pattern,
       
   974  			  FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
       
   975  	antialias = FcTrue;
       
   976      
       
   977      if (antialias) {
       
   978  	cairo_subpixel_order_t subpixel_order;
       
   979 +	int lcd_filter;
       
   980  
       
   981  	/* disable hinting if requested */
       
   982  	if (FcPatternGetBool (pattern,
       
   983  			      FC_HINTING, 0, &hinting) != FcResultMatch)
       
   984  	    hinting = FcTrue;
       
   985  
       
   986  	if (FcPatternGetInteger (pattern,
       
   987  				 FC_RGBA, 0, &rgba) != FcResultMatch)
       
   988 @@ -1389,16 +1624,35 @@ _get_pattern_ft_options (FcPattern *patt
       
   989  	    break;
       
   990  	}
       
   991  
       
   992  	if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
       
   993  	    ft_options.base.subpixel_order = subpixel_order;
       
   994  	    ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
       
   995  	}
       
   996  
       
   997 +	if (FcPatternGetInteger (pattern,
       
   998 +				 FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
       
   999 +	{
       
  1000 +	    switch (lcd_filter) {
       
  1001 +	    case FC_LCD_NONE:
       
  1002 +		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
       
  1003 +		break;
       
  1004 +	    case FC_LCD_DEFAULT:
       
  1005 +		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
       
  1006 +		break;
       
  1007 +	    case FC_LCD_LIGHT:
       
  1008 +		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
       
  1009 +		break;
       
  1010 +	    case FC_LCD_LEGACY:
       
  1011 +		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
       
  1012 +		break;
       
  1013 +	    }
       
  1014 +	}
       
  1015 +
       
  1016  #ifdef FC_HINT_STYLE    
       
  1017  	if (FcPatternGetInteger (pattern, 
       
  1018  				 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
       
  1019  	    hintstyle = FC_HINT_FULL;
       
  1020  
       
  1021  	if (!hinting)
       
  1022  	    hintstyle = FC_HINT_NONE;
       
  1023  
       
  1024 @@ -1490,16 +1744,22 @@ _cairo_ft_options_merge (cairo_ft_option
       
  1025      }
       
  1026  
       
  1027      if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
       
  1028  	options->base.hint_style = other->base.hint_style;
       
  1029  
       
  1030      if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
       
  1031  	options->base.hint_style = CAIRO_HINT_STYLE_NONE;
       
  1032  
       
  1033 +    if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
       
  1034 +	options->base.lcd_filter = other->base.lcd_filter;
       
  1035 +
       
  1036 +    if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
       
  1037 +	options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
       
  1038 +
       
  1039      if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
       
  1040  	if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
       
  1041  	    load_flags |= FT_LOAD_NO_HINTING;
       
  1042  	else
       
  1043  	    load_target = FT_LOAD_TARGET_MONO;
       
  1044  	load_flags |= FT_LOAD_MONOCHROME;
       
  1045      } else {
       
  1046  	switch (options->base.hint_style) {
       
  1047 @@ -1513,21 +1773,21 @@ _cairo_ft_options_merge (cairo_ft_option
       
  1048  	    break;
       
  1049  	case CAIRO_HINT_STYLE_FULL:
       
  1050  	case CAIRO_HINT_STYLE_DEFAULT:
       
  1051  	    if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
       
  1052  		switch (options->base.subpixel_order) {
       
  1053  		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
       
  1054  		case CAIRO_SUBPIXEL_ORDER_RGB:
       
  1055  		case CAIRO_SUBPIXEL_ORDER_BGR:
       
  1056 -		    load_target |= FT_LOAD_TARGET_LCD;
       
  1057 +		    load_target = FT_LOAD_TARGET_LCD;
       
  1058  		    break;
       
  1059  		case CAIRO_SUBPIXEL_ORDER_VRGB:
       
  1060  		case CAIRO_SUBPIXEL_ORDER_VBGR:
       
  1061 -		    load_target |= FT_LOAD_TARGET_LCD_V;
       
  1062 +		    load_target = FT_LOAD_TARGET_LCD_V;
       
  1063  		break;
       
  1064  		}
       
  1065  	    }
       
  1066  	    break;
       
  1067  	}
       
  1068      }
       
  1069  
       
  1070      options->load_flags = load_flags | load_target;
       
  1071 @@ -2510,16 +2770,44 @@ _cairo_ft_font_options_substitute (const
       
  1072  		rgba = FC_RGBA_NONE;
       
  1073  	    }
       
  1074  
       
  1075  	    if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
       
  1076  		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
  1077  	}
       
  1078      }
       
  1079  
       
  1080 +    if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
       
  1081 +    {
       
  1082 +	if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
       
  1083 +	{
       
  1084 +	    int lcd_filter;
       
  1085 +
       
  1086 +	    switch (options->lcd_filter) {
       
  1087 +	    case CAIRO_LCD_FILTER_NONE:
       
  1088 +		lcd_filter = FT_LCD_FILTER_NONE;
       
  1089 +		break;
       
  1090 +	    case CAIRO_LCD_FILTER_DEFAULT:
       
  1091 +	    case CAIRO_LCD_FILTER_INTRA_PIXEL:
       
  1092 +		lcd_filter = FT_LCD_FILTER_LEGACY;
       
  1093 +		break;
       
  1094 +	    case CAIRO_LCD_FILTER_FIR3:
       
  1095 +		lcd_filter = FT_LCD_FILTER_LIGHT;
       
  1096 +		break;
       
  1097 +	    default:
       
  1098 +	    case CAIRO_LCD_FILTER_FIR5:
       
  1099 +		lcd_filter = FT_LCD_FILTER_DEFAULT;
       
  1100 +		break;
       
  1101 +	    }
       
  1102 +
       
  1103 +	    if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
       
  1104 +		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
  1105 +	}
       
  1106 +    }
       
  1107 +
       
  1108      if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
       
  1109      {
       
  1110  	if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
       
  1111  	{
       
  1112  	    if (! FcPatternAddBool (pattern,
       
  1113  			            FC_HINTING,
       
  1114  				    options->hint_style != CAIRO_HINT_STYLE_NONE))
       
  1115  		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
       
  1116 diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c
       
  1117 --- a/gfx/cairo/cairo/src/cairo-surface.c
       
  1118 +++ b/gfx/cairo/cairo/src/cairo-surface.c
       
  1119 @@ -60,16 +60,17 @@ const cairo_surface_t name = {					\
       
  1120      0.0,				/* y_fallback_resolution */	\
       
  1121      NULL,				/* clip */		\
       
  1122      0,					/* next_clip_serial */	\
       
  1123      0,					/* current_clip_serial */	\
       
  1124      FALSE,				/* is_snapshot */	\
       
  1125      FALSE,				/* has_font_options */	\
       
  1126      { CAIRO_ANTIALIAS_DEFAULT,		/* antialias */		\
       
  1127        CAIRO_SUBPIXEL_ORDER_DEFAULT,	/* subpixel_order */	\
       
  1128 +      CAIRO_LCD_FILTER_DEFAULT,		/* lcd_filter */	\
       
  1129        CAIRO_HINT_STYLE_DEFAULT,		/* hint_style */	\
       
  1130        CAIRO_HINT_METRICS_DEFAULT	/* hint_metrics */	\
       
  1131      }					/* font_options */	\
       
  1132  }
       
  1133  
       
  1134  static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
       
  1135  static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
       
  1136  static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
       
  1137 diff --git a/gfx/cairo/cairo/src/cairo-types-private.h b/gfx/cairo/cairo/src/cairo-types-private.h
       
  1138 --- a/gfx/cairo/cairo/src/cairo-types-private.h
       
  1139 +++ b/gfx/cairo/cairo/src/cairo-types-private.h
       
  1140 @@ -110,19 +110,45 @@ struct _cairo_array {
       
  1141      unsigned int size;
       
  1142      unsigned int num_elements;
       
  1143      unsigned int element_size;
       
  1144      char **elements;
       
  1145  
       
  1146      cairo_bool_t is_snapshot;
       
  1147  };
       
  1148  
       
  1149 +
       
  1150 +/**
       
  1151 + * cairo_lcd_filter_t:
       
  1152 + * @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for
       
  1153 + *   font backend and target device
       
  1154 + * @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
       
  1155 + * @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter
       
  1156 + * @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel
       
  1157 + * @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel
       
  1158 + *
       
  1159 + * The LCD filter specifies the low-pass filter applied to LCD-optimized
       
  1160 + * bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
       
  1161 + *
       
  1162 + * Note: This API was temporarily made available in the public
       
  1163 + * interface during the 1.7.x development series, but was made private
       
  1164 + * before 1.8.
       
  1165 + **/
       
  1166 +typedef enum _cairo_lcd_filter {
       
  1167 +    CAIRO_LCD_FILTER_DEFAULT,
       
  1168 +    CAIRO_LCD_FILTER_NONE,
       
  1169 +    CAIRO_LCD_FILTER_INTRA_PIXEL,
       
  1170 +    CAIRO_LCD_FILTER_FIR3,
       
  1171 +    CAIRO_LCD_FILTER_FIR5
       
  1172 +} cairo_lcd_filter_t;
       
  1173 +
       
  1174  struct _cairo_font_options {
       
  1175      cairo_antialias_t antialias;
       
  1176      cairo_subpixel_order_t subpixel_order;
       
  1177 +    cairo_lcd_filter_t lcd_filter;
       
  1178      cairo_hint_style_t hint_style;
       
  1179      cairo_hint_metrics_t hint_metrics;
       
  1180  };
       
  1181  
       
  1182  typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
       
  1183  
       
  1184  struct _cairo_cache {
       
  1185      cairo_hash_table_t *hash_table;
       
  1186 diff --git a/gfx/cairo/cairo/src/cairo-xlib-screen.c b/gfx/cairo/cairo/src/cairo-xlib-screen.c
       
  1187 --- a/gfx/cairo/cairo/src/cairo-xlib-screen.c
       
  1188 +++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c
       
  1189 @@ -145,23 +145,32 @@ get_integer_default (Display    *dpy,
       
  1190  static void
       
  1191  _cairo_xlib_init_screen_font_options (Display *dpy,
       
  1192  				      cairo_xlib_screen_info_t *info)
       
  1193  {
       
  1194      cairo_bool_t xft_hinting;
       
  1195      cairo_bool_t xft_antialias;
       
  1196      int xft_hintstyle;
       
  1197      int xft_rgba;
       
  1198 +    int xft_lcdfilter;
       
  1199      cairo_antialias_t antialias;
       
  1200      cairo_subpixel_order_t subpixel_order;
       
  1201 +    cairo_lcd_filter_t lcd_filter;
       
  1202      cairo_hint_style_t hint_style;
       
  1203  
       
  1204      if (!get_boolean_default (dpy, "antialias", &xft_antialias))
       
  1205  	xft_antialias = TRUE;
       
  1206  
       
  1207 +    if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
       
  1208 +	/* -1 is an non-existant Fontconfig constant used to differentiate
       
  1209 +	 * the case when no lcdfilter property is available.
       
  1210 +	 */
       
  1211 +	xft_lcdfilter = -1;
       
  1212 +    }
       
  1213 +
       
  1214      if (!get_boolean_default (dpy, "hinting", &xft_hinting))
       
  1215  	xft_hinting = TRUE;
       
  1216  
       
  1217      if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
       
  1218  	xft_hintstyle = FC_HINT_FULL;
       
  1219  
       
  1220      if (!get_integer_default (dpy, "rgba", &xft_rgba))
       
  1221      {
       
  1222 @@ -234,28 +243,47 @@ _cairo_xlib_init_screen_font_options (Di
       
  1223  	subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
       
  1224  	break;
       
  1225      case FC_RGBA_UNKNOWN:
       
  1226      case FC_RGBA_NONE:
       
  1227      default:
       
  1228  	subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
       
  1229      }
       
  1230  
       
  1231 +    switch (xft_lcdfilter) {
       
  1232 +    case FC_LCD_NONE:
       
  1233 +	lcd_filter = CAIRO_LCD_FILTER_NONE;
       
  1234 +	break;
       
  1235 +    case FC_LCD_DEFAULT:
       
  1236 +	lcd_filter = CAIRO_LCD_FILTER_FIR5;
       
  1237 +	break;
       
  1238 +    case FC_LCD_LIGHT:
       
  1239 +	lcd_filter = CAIRO_LCD_FILTER_FIR3;
       
  1240 +	break;
       
  1241 +    case FC_LCD_LEGACY:
       
  1242 +	lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
       
  1243 +	break;
       
  1244 +    default:
       
  1245 +	lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
       
  1246 +	break;
       
  1247 +    }
       
  1248 +
       
  1249      if (xft_antialias) {
       
  1250  	if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
       
  1251  	    antialias = CAIRO_ANTIALIAS_GRAY;
       
  1252  	else
       
  1253  	    antialias = CAIRO_ANTIALIAS_SUBPIXEL;
       
  1254      } else {
       
  1255  	antialias = CAIRO_ANTIALIAS_NONE;
       
  1256      }
       
  1257  
       
  1258      cairo_font_options_set_hint_style (&info->font_options, hint_style);
       
  1259      cairo_font_options_set_antialias (&info->font_options, antialias);
       
  1260      cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
       
  1261 +    _cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
       
  1262      cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
       
  1263  }
       
  1264  
       
  1265  cairo_xlib_screen_info_t *
       
  1266  _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
       
  1267  {
       
  1268      assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
       
  1269  
       
  1270 diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h
       
  1271 --- a/gfx/cairo/cairo/src/cairoint.h
       
  1272 +++ b/gfx/cairo/cairo/src/cairoint.h
       
  1273 @@ -1444,16 +1444,23 @@ extern const cairo_private uint16_t _cai
       
  1274  
       
  1275  cairo_private void
       
  1276  _cairo_font_options_init_default (cairo_font_options_t *options);
       
  1277  
       
  1278  cairo_private void
       
  1279  _cairo_font_options_init_copy (cairo_font_options_t		*options,
       
  1280  			       const cairo_font_options_t	*other);
       
  1281  
       
  1282 +cairo_private void
       
  1283 +_cairo_font_options_set_lcd_filter (cairo_font_options_t   *options,
       
  1284 +				   cairo_lcd_filter_t  lcd_filter);
       
  1285 +
       
  1286 +cairo_private cairo_lcd_filter_t
       
  1287 +_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options);
       
  1288 +
       
  1289  /* cairo-hull.c */
       
  1290  cairo_private cairo_status_t
       
  1291  _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
       
  1292  
       
  1293  /* cairo-lzw.c */
       
  1294  cairo_private unsigned char *
       
  1295  _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out);
       
  1296