updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / cairo-cleartype / cairo-9999-cleartype.patch
blobc4ae211d04c0f7cc513748ebac030048c083aca2
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
4 @@ -57,6 +57,8 @@
5 #include FT_SYNTHESIS_H
6 #endif
8 +#define FIR_FILTER 1
10 #if HAVE_FT_LIBRARY_SETLCDFILTER
11 #include FT_LCD_FILTER_H
12 #endif
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 };
19 static cairo_bool_t
20 _has_unlocked_face (const void *entry)
22 @@ -1114,6 +1118,7 @@ _get_bitmap_surface (FT_Bitmap *bi
23 unsigned char *data;
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;
34 - } else {
35 + } else
36 +#ifdef FIR_FILTER
37 + {
38 + unsigned char* line;
39 + unsigned char* bufBitmap;
40 + int pitch;
41 + unsigned char *data_rgba;
42 + unsigned int width_rgba, stride_rgba;
43 + int vmul = 1;
44 + int hmul = 1;
46 + switch (font_options->subpixel_order) {
47 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
48 + case CAIRO_SUBPIXEL_ORDER_RGB:
49 + case CAIRO_SUBPIXEL_ORDER_BGR:
50 + default:
51 + width /= 3;
52 + hmul = 3;
53 + break;
54 + case CAIRO_SUBPIXEL_ORDER_VRGB:
55 + case CAIRO_SUBPIXEL_ORDER_VBGR:
56 + vmul = 3;
57 + height /= 3;
58 + break;
59 + }
60 + /*
61 + * Filter the glyph to soften the color fringes
62 + */
63 + width_rgba = width;
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.
72 + */
73 + pitch = bitmap->pitch;
74 + line = (unsigned char*)bitmap->buffer;
75 + if ( pitch < 0 )
76 + line -= pitch*(height-1);
78 + bufBitmap = line;
80 + switch (font_options->subpixel_order) {
81 + case CAIRO_SUBPIXEL_ORDER_DEFAULT:
82 + case CAIRO_SUBPIXEL_ORDER_RGB:
83 + case CAIRO_SUBPIXEL_ORDER_BGR:
84 + {
85 + int h;
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;
91 + int nn, val, val2;
93 + val = p[0];
94 + for (nn = 0; nn < 3; nn++)
95 + pix[2 + nn] += val * fir_filter[nn];
97 + val = p[1];
98 + for (nn = 0; nn < 4; nn++)
99 + pix[1 + nn] += val * fir_filter[nn];
101 + p += 2;
103 + for ( ; p < limit; p++ ) {
104 + val = p[0];
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;
122 + break;
123 + case CAIRO_SUBPIXEL_ORDER_VRGB:
124 + case CAIRO_SUBPIXEL_ORDER_VBGR:
126 + int w;
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;
132 + int nn, val, val2;
134 + val = p[0];
135 + for (nn = 0; nn < 3; nn++)
136 + pix[2 + nn] += val*fir_filter[nn];
138 + val = p[pitch];
139 + for (nn = 0; nn < 4; nn++ )
140 + pix[1 + nn] += val * fir_filter[nn];
142 + p += 2*pitch;
143 + for ( ; p < limit; p += pitch ) {
144 + val = p[0];
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;
163 + break;
164 + default: /* shouldn't happen */
165 + break;
168 + /* now copy the resulting graymap into an ARGB32 image */
170 + unsigned char* in_line = bufBitmap;
171 + unsigned char* out_line = data_rgba;
172 + int h = height;
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;
180 + int w;
182 + for (w = width; w > 0; w--, in += 3, out += 1) {
183 + int r = in[0];
184 + int g = in[1];
185 + int b = in[2];
187 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
190 + break;
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;
195 + int w;
197 + for (w = width; w > 0; w--, in += 3, out += 1) {
198 + int r = in[2];
199 + int g = in[1];
200 + int b = in[0];
202 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
205 + break;
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;
210 + int w;
212 + for (w = width; w > 0; w--, in += 1, out += 1) {
213 + int r = in[0];
214 + int g = in[pitch];
215 + int b = in[pitch*2];
217 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
220 + break;
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;
225 + int w;
227 + for (w = width; w > 0; w--, in += 1, out += 1) {
228 + int r = in[2*pitch];
229 + int g = in[pitch];
230 + int b = in[0];
232 + out[0] = (g << 24) | (r << 16) | (g << 8) | b;
235 + break;
239 + if (own_buffer)
240 + free (bitmap->buffer);
241 + data = data_rgba;
242 + stride = stride_rgba;
243 + format = CAIRO_FORMAT_ARGB32;
244 + subpixel = TRUE;
245 + break;
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 */
257 break;
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;
269 FT_Bitmap bitmap;
270 FT_BBox cbox;
271 - unsigned int width, height;
272 + FT_Matrix matrix;
273 + int hmul = 1;
274 + int vmul = 1;
275 + unsigned int width, height, stride;
276 + cairo_bool_t subpixel = FALSE;
277 cairo_status_t status;
278 - FT_Error fterror;
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;
285 - break;
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;
293 - break;
295 - case CAIRO_SUBPIXEL_ORDER_VRGB:
296 - case CAIRO_SUBPIXEL_ORDER_VBGR:
297 - render_mode = FT_RENDER_MODE_LCD_V;
298 - break;
301 - switch (font_options->lcd_filter) {
302 - case CAIRO_LCD_FILTER_NONE:
303 - lcd_filter = FT_LCD_FILTER_NONE;
304 - break;
305 - case CAIRO_LCD_FILTER_DEFAULT:
306 - case CAIRO_LCD_FILTER_INTRA_PIXEL:
307 - lcd_filter = FT_LCD_FILTER_LEGACY;
308 - break;
309 - case CAIRO_LCD_FILTER_FIR3:
310 - lcd_filter = FT_LCD_FILTER_LIGHT;
311 - break;
312 - case CAIRO_LCD_FILTER_FIR5:
313 - lcd_filter = FT_LCD_FILTER_DEFAULT;
314 - break;
317 - break;
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;
340 break;
341 - case FT_RENDER_MODE_LCD:
342 - case FT_RENDER_MODE_LCD_V:
343 + case CAIRO_ANTIALIAS_SUBPIXEL:
344 format= CAIRO_FORMAT_ARGB32;
345 break;
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:
351 default:
352 format = CAIRO_FORMAT_A8;
353 break;
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;
358 - } else {
359 + } else {
361 - int bitmap_size;
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;
369 - } else {
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;
375 - } else {
376 - rgba = FC_RGBA_VRGB;
378 - break;
379 - case FT_RENDER_MODE_MONO:
380 - case FT_RENDER_MODE_LIGHT:
381 - case FT_RENDER_MODE_NORMAL:
382 - case FT_RENDER_MODE_MAX:
383 - default:
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;
389 + break;
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;
395 break;
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:
405 + default:
406 + matrix.xx *= 3;
407 + hmul = 3;
408 + subpixel = TRUE;
409 +#ifdef FIR_FILTER
410 + cbox.xMin -= 64;
411 + cbox.xMax += 64;
412 + width += 2;
413 #endif
415 - fterror = FT_Render_Glyph (face->glyph, render_mode);
417 -#if HAVE_FT_LIBRARY_SETLCDFILTER
418 - FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
419 + break;
420 + case CAIRO_SUBPIXEL_ORDER_VRGB:
421 + case CAIRO_SUBPIXEL_ORDER_VBGR:
422 + matrix.yy *= 3;
423 + vmul = 3;
424 + subpixel = TRUE;
425 +#ifdef FIR_FILTER
426 + cbox.yMin -= 64;
427 + cbox.yMax += 64;
428 + height += 2;
429 #endif
430 + break;
432 + FT_Outline_Transform (outline, &matrix);
434 - if (fterror != 0)
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,
442 - face->glyph,
443 - render_mode);
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);
464 - /* Note:
465 - * _get_bitmap_surface will free bitmap.buffer if there is an error
466 - */
467 status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
468 - if (unlikely (status))
469 + if (status)
470 return 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.
476 - */
477 - cairo_surface_set_device_offset (&(*surface)->base,
478 - (double)-glyphslot->bitmap_left,
479 - (double)+glyphslot->bitmap_top);
482 + /*
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.
487 + */
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;