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