1 diff -rupN cairo-9999.new/src/cairo-ft-font.c cairo-9999/src/cairo-ft-font.c
2 --- cairo-9999.new/src/cairo-ft-font.c 2010-08-06 21:51:21.603000022 +0300
3 +++ cairo-9999/src/cairo-ft-font.c 2010-08-06 21:52:00.926000031 +0300
5 #include FT_SYNTHESIS_H
10 #if HAVE_FT_LIBRARY_SETLCDFILTER
11 #include FT_LCD_FILTER_H
13 @@ -607,6 +609,8 @@ _cairo_ft_unscaled_font_destroy (void *a
14 _cairo_ft_unscaled_font_fini (unscaled);
17 +static const int fir_filter[5] = { 0x1C, 0x38, 0x55, 0x38, 0x1C };
20 _has_unlocked_face (const void *entry)
22 @@ -1114,6 +1118,7 @@ _get_bitmap_surface (FT_Bitmap *bi
24 int format = CAIRO_FORMAT_A8;
25 cairo_image_surface_t *image;
26 + cairo_bool_t subpixel = FALSE;
28 width = bitmap->width;
29 height = bitmap->rows;
30 @@ -1183,7 +1188,220 @@ _get_bitmap_surface (FT_Bitmap *bi
33 format = CAIRO_FORMAT_A8;
38 + unsigned char* line;
39 + unsigned char* bufBitmap;
41 + unsigned char *data_rgba;
42 + unsigned int width_rgba, stride_rgba;
46 + switch (font_options->subpixel_order) {
47 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
48 + case CAIRO_SUBPIXEL_ORDER_RGB:
49 + case CAIRO_SUBPIXEL_ORDER_BGR:
54 + case CAIRO_SUBPIXEL_ORDER_VRGB:
55 + case CAIRO_SUBPIXEL_ORDER_VBGR:
61 + * Filter the glyph to soften the color fringes
64 + stride = bitmap->pitch;
65 + stride_rgba = (width_rgba * 4 + 3) & ~3;
66 + data_rgba = calloc (1, stride_rgba * height);
68 + /* perform in-place FIR filtering in either the horizontal or
69 + * vertical direction. We're going to modify the RGB graymap,
70 + * but that's ok, because we either own it, or its part of
71 + * the FreeType glyph slot, which will not be used anymore.
73 + pitch = bitmap->pitch;
74 + line = (unsigned char*)bitmap->buffer;
76 + line -= pitch*(height-1);
80 + switch (font_options->subpixel_order) {
81 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
82 + case CAIRO_SUBPIXEL_ORDER_RGB:
83 + case CAIRO_SUBPIXEL_ORDER_BGR:
87 + for ( h = height; h > 0; h--, line += pitch ) {
88 + int pix[6] = { 0, 0, 0, 0, 0, 0 };
89 + unsigned char* p = line;
90 + unsigned char* limit = line + width*3;
94 + for (nn = 0; nn < 3; nn++)
95 + pix[2 + nn] += val * fir_filter[nn];
98 + for (nn = 0; nn < 4; nn++)
99 + pix[1 + nn] += val * fir_filter[nn];
103 + for ( ; p < limit; p++ ) {
105 + for (nn = 0; nn < 5; nn++)
106 + pix[nn] += val * fir_filter[nn];
108 + val2 = pix[0] / 256;
109 + val2 |= -(val2 >> 8);
110 + p[-2] = (unsigned char)val2;
112 + for (nn = 0; nn < 5; nn++)
113 + pix[nn] = pix[nn + 1];
115 + for (nn = 0; nn < 2; nn++ ) {
116 + val2 = pix[nn] / 256;
117 + val2 |= -(val2 >> 8);
118 + p[nn - 2] = (unsigned char)val2;
123 + case CAIRO_SUBPIXEL_ORDER_VRGB:
124 + case CAIRO_SUBPIXEL_ORDER_VBGR:
128 + for (w = 0; w < width; w++ ) {
129 + int pix[6] = { 0, 0, 0, 0, 0, 0 };
130 + unsigned char* p = bufBitmap + w;
131 + unsigned char* limit = bufBitmap + w + height*3*pitch;
135 + for (nn = 0; nn < 3; nn++)
136 + pix[2 + nn] += val*fir_filter[nn];
139 + for (nn = 0; nn < 4; nn++ )
140 + pix[1 + nn] += val * fir_filter[nn];
143 + for ( ; p < limit; p += pitch ) {
145 + for (nn = 0; nn < 5; nn++ )
146 + pix[nn] += val * fir_filter[nn];
148 + val2 = pix[0] / 256;
149 + val2 |= -(val2 >> 8);
150 + p[-2 * pitch] = (unsigned char)val2;
152 + for (nn = 0; nn < 5; nn++)
153 + pix[nn] = pix[nn+1];
156 + for (nn = 0; nn < 2; nn++) {
157 + val2 = pix[nn] / 256;
158 + val2 |= -(val2 >> 8);
159 + p[(nn - 2) * pitch] = (unsigned char)val2;
164 + default: /* shouldn't happen */
168 + /* now copy the resulting graymap into an ARGB32 image */
170 + unsigned char* in_line = bufBitmap;
171 + unsigned char* out_line = data_rgba;
174 + switch (font_options->subpixel_order) {
175 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
176 + case CAIRO_SUBPIXEL_ORDER_RGB:
177 + for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) {
178 + unsigned char* in = in_line;
179 + int* out = (int*)out_line;
182 + for (w = width; w > 0; w--, in += 3, out += 1) {
187 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
191 + case CAIRO_SUBPIXEL_ORDER_BGR:
192 + for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) {
193 + unsigned char* in = in_line;
194 + int* out = (int*)out_line;
197 + for (w = width; w > 0; w--, in += 3, out += 1) {
202 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
206 + case CAIRO_SUBPIXEL_ORDER_VRGB:
207 + for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) {
208 + unsigned char* in = in_line;
209 + int* out = (int*)out_line;
212 + for (w = width; w > 0; w--, in += 1, out += 1) {
215 + int b = in[pitch*2];
217 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
221 + case CAIRO_SUBPIXEL_ORDER_VBGR:
222 + for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) {
223 + unsigned char* in = in_line;
224 + int* out = (int*)out_line;
227 + for (w = width; w > 0; w--, in += 1, out += 1) {
228 + int r = in[2*pitch];
232 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
240 + free (bitmap->buffer);
242 + stride = stride_rgba;
243 + format = CAIRO_FORMAT_ARGB32;
247 +#else /* !FIR_FILTER */
249 /* if we get there, the data from the source bitmap
250 * really comes from _fill_xrender_bitmap, and is
251 * made of 32-bit ARGB or ABGR values */
252 @@ -1194,6 +1412,7 @@ _get_bitmap_surface (FT_Bitmap *bi
253 stride = bitmap->pitch;
254 format = CAIRO_FORMAT_ARGB32;
256 +#endif /* !FIR_FILTER */
258 case FT_PIXEL_MODE_GRAY2:
259 case FT_PIXEL_MODE_GRAY4:
260 @@ -1244,59 +1463,16 @@ _render_glyph_outline (FT_Face
261 cairo_font_options_t *font_options,
262 cairo_image_surface_t **surface)
264 - int rgba = FC_RGBA_UNKNOWN;
265 - int lcd_filter = FT_LCD_FILTER_LEGACY;
266 - FT_GlyphSlot glyphslot = face->glyph;
267 + FT_GlyphSlot glyphslot = face->glyph;
268 FT_Outline *outline = &glyphslot->outline;
271 - unsigned int width, height;
275 + unsigned int width, height, stride;
276 + cairo_bool_t subpixel = FALSE;
277 cairo_status_t status;
279 - FT_Library library = glyphslot->library;
280 - FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
282 - switch (font_options->antialias) {
283 - case CAIRO_ANTIALIAS_NONE:
284 - render_mode = FT_RENDER_MODE_MONO;
287 - case CAIRO_ANTIALIAS_SUBPIXEL:
288 - switch (font_options->subpixel_order) {
289 - case CAIRO_SUBPIXEL_ORDER_DEFAULT:
290 - case CAIRO_SUBPIXEL_ORDER_RGB:
291 - case CAIRO_SUBPIXEL_ORDER_BGR:
292 - render_mode = FT_RENDER_MODE_LCD;
295 - case CAIRO_SUBPIXEL_ORDER_VRGB:
296 - case CAIRO_SUBPIXEL_ORDER_VBGR:
297 - render_mode = FT_RENDER_MODE_LCD_V;
301 - switch (font_options->lcd_filter) {
302 - case CAIRO_LCD_FILTER_NONE:
303 - lcd_filter = FT_LCD_FILTER_NONE;
305 - case CAIRO_LCD_FILTER_DEFAULT:
306 - case CAIRO_LCD_FILTER_INTRA_PIXEL:
307 - lcd_filter = FT_LCD_FILTER_LEGACY;
309 - case CAIRO_LCD_FILTER_FIR3:
310 - lcd_filter = FT_LCD_FILTER_LIGHT;
312 - case CAIRO_LCD_FILTER_FIR5:
313 - lcd_filter = FT_LCD_FILTER_DEFAULT;
319 - case CAIRO_ANTIALIAS_DEFAULT:
320 - case CAIRO_ANTIALIAS_GRAY:
321 - render_mode = FT_RENDER_MODE_NORMAL;
324 FT_Outline_Get_CBox (outline, &cbox);
326 @@ -1307,21 +1483,20 @@ _render_glyph_outline (FT_Face
328 width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
329 height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
330 + stride = (width * hmul + 3) & ~3;
332 if (width * height == 0) {
333 cairo_format_t format;
334 /* Looks like fb handles zero-sized images just fine */
335 - switch (render_mode) {
336 - case FT_RENDER_MODE_MONO:
337 + switch (font_options->antialias) {
338 + case CAIRO_ANTIALIAS_NONE:
339 format = CAIRO_FORMAT_A1;
341 - case FT_RENDER_MODE_LCD:
342 - case FT_RENDER_MODE_LCD_V:
343 + case CAIRO_ANTIALIAS_SUBPIXEL:
344 format= CAIRO_FORMAT_ARGB32;
346 - case FT_RENDER_MODE_LIGHT:
347 - case FT_RENDER_MODE_NORMAL:
348 - case FT_RENDER_MODE_MAX:
349 + case CAIRO_ANTIALIAS_DEFAULT:
350 + case CAIRO_ANTIALIAS_GRAY:
352 format = CAIRO_FORMAT_A8;
354 @@ -1331,75 +1506,86 @@ _render_glyph_outline (FT_Face
355 cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
356 if ((*surface)->base.status)
357 return (*surface)->base.status;
362 + matrix.xx = matrix.yy = 0x10000L;
363 + matrix.xy = matrix.yx = 0;
365 - switch (render_mode) {
366 - case FT_RENDER_MODE_LCD:
367 - if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
368 - rgba = FC_RGBA_BGR;
370 - rgba = FC_RGBA_RGB;
372 - case FT_RENDER_MODE_LCD_V:
373 - if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
374 - rgba = FC_RGBA_VBGR;
376 - rgba = FC_RGBA_VRGB;
379 - case FT_RENDER_MODE_MONO:
380 - case FT_RENDER_MODE_LIGHT:
381 - case FT_RENDER_MODE_NORMAL:
382 - case FT_RENDER_MODE_MAX:
384 + switch (font_options->antialias) {
385 + case CAIRO_ANTIALIAS_NONE:
386 + bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
387 + bitmap.num_grays = 1;
388 + stride = ((width + 31) & -32) >> 3;
390 + case CAIRO_ANTIALIAS_DEFAULT:
391 + case CAIRO_ANTIALIAS_GRAY:
392 + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
393 + bitmap.num_grays = 256;
394 + stride = (width + 3) & -4;
398 -#if HAVE_FT_LIBRARY_SETLCDFILTER
399 - FT_Library_SetLcdFilter (library, lcd_filter);
400 + case CAIRO_ANTIALIAS_SUBPIXEL:
401 + switch (font_options->subpixel_order) {
402 + case CAIRO_SUBPIXEL_ORDER_RGB:
403 + case CAIRO_SUBPIXEL_ORDER_BGR:
404 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
415 - fterror = FT_Render_Glyph (face->glyph, render_mode);
417 -#if HAVE_FT_LIBRARY_SETLCDFILTER
418 - FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
420 + case CAIRO_SUBPIXEL_ORDER_VRGB:
421 + case CAIRO_SUBPIXEL_ORDER_VBGR:
432 + FT_Outline_Transform (outline, &matrix);
435 - return _cairo_error (CAIRO_STATUS_NO_MEMORY);
436 + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
437 + bitmap.num_grays = 256;
438 + stride = (width * hmul + 3) & -4;
441 - bitmap_size = _compute_xrender_bitmap_size (&bitmap,
444 - if (bitmap_size < 0)
445 + bitmap.pitch = stride;
446 + bitmap.width = width * hmul;
447 + bitmap.rows = height * vmul;
448 + bitmap.buffer = calloc (stride, bitmap.rows);
449 + if (bitmap.buffer == NULL)
450 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
452 - bitmap.buffer = calloc (1, bitmap_size);
453 - if (bitmap.buffer == NULL)
454 - return _cairo_error (CAIRO_STATUS_NO_MEMORY);
455 + FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
457 - _fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
458 - (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
459 + if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
460 + free (bitmap.buffer);
461 + return _cairo_error (CAIRO_STATUS_NO_MEMORY);
465 - * _get_bitmap_surface will free bitmap.buffer if there is an error
467 status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
468 - if (unlikely (status))
472 - /* Note: the font's coordinate system is upside down from ours, so the
473 - * Y coordinate of the control box needs to be negated. Moreover, device
474 - * offsets are position of glyph origin relative to top left while xMin
475 - * and yMax are offsets of top left relative to origin. Another negation.
477 - cairo_surface_set_device_offset (&(*surface)->base,
478 - (double)-glyphslot->bitmap_left,
479 - (double)+glyphslot->bitmap_top);
483 + * Note: the font's coordinate system is upside down from ours, so the
484 + * Y coordinate of the control box needs to be negated. Moreover, device
485 + * offsets are position of glyph origin relative to top left while xMin
486 + * and yMax are offsets of top left relative to origin. Another negation.
488 + cairo_surface_set_device_offset (&(*surface)->base,
489 + floor (-(double) cbox.xMin / 64.0),
490 + floor (+(double) cbox.yMax / 64.0));
492 return CAIRO_STATUS_SUCCESS;