1 |
#! /bin/sh /usr/share/dpatch/dpatch-run |
2 |
## 04_lcd_filter.dpatch by Fabien Tassin <fta@ubuntu.com> |
3 |
## |
4 |
## All lines beginning with `## DP:' are a description of the patch. |
5 |
## DP: From git rev 5d887ad5dca5af0f8216830d1b04d08a5aba9bee |
6 |
|
7 |
@DPATCH@ |
8 |
diff -urNad cairo-1.8.0~/src/cairo-font-options.c cairo-1.8.0/src/cairo-font-options.c |
9 |
--- cairo-1.8.0~/src/cairo-font-options.c 2008-09-25 22:30:14.000000000 +0200 |
10 |
+++ cairo-1.8.0/src/cairo-font-options.c 2008-10-14 15:01:37.000000000 +0200 |
11 |
@@ -39,6 +39,7 @@ |
12 |
static const cairo_font_options_t _cairo_font_options_nil = { |
13 |
CAIRO_ANTIALIAS_DEFAULT, |
14 |
CAIRO_SUBPIXEL_ORDER_DEFAULT, |
15 |
+ CAIRO_LCD_FILTER_DEFAULT, |
16 |
CAIRO_HINT_STYLE_DEFAULT, |
17 |
CAIRO_HINT_METRICS_DEFAULT |
18 |
}; |
19 |
@@ -54,6 +55,7 @@ |
20 |
{ |
21 |
options->antialias = CAIRO_ANTIALIAS_DEFAULT; |
22 |
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; |
23 |
+ options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT; |
24 |
options->hint_style = CAIRO_HINT_STYLE_DEFAULT; |
25 |
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; |
26 |
} |
27 |
@@ -64,6 +66,7 @@ |
28 |
{ |
29 |
options->antialias = other->antialias; |
30 |
options->subpixel_order = other->subpixel_order; |
31 |
+ options->lcd_filter = other->lcd_filter; |
32 |
options->hint_style = other->hint_style; |
33 |
options->hint_metrics = other->hint_metrics; |
34 |
} |
35 |
@@ -189,6 +192,8 @@ |
36 |
options->antialias = other->antialias; |
37 |
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) |
38 |
options->subpixel_order = other->subpixel_order; |
39 |
+ if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT) |
40 |
+ options->lcd_filter = other->lcd_filter; |
41 |
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT) |
42 |
options->hint_style = other->hint_style; |
43 |
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT) |
44 |
@@ -221,6 +226,7 @@ |
45 |
|
46 |
return (options->antialias == other->antialias && |
47 |
options->subpixel_order == other->subpixel_order && |
48 |
+ options->lcd_filter == other->lcd_filter && |
49 |
options->hint_style == other->hint_style && |
50 |
options->hint_metrics == other->hint_metrics); |
51 |
} |
52 |
@@ -246,7 +252,8 @@ |
53 |
|
54 |
return ((options->antialias) | |
55 |
(options->subpixel_order << 4) | |
56 |
- (options->hint_style << 8) | |
57 |
+ (options->lcd_filter << 8) | |
58 |
+ (options->hint_style << 12) | |
59 |
(options->hint_metrics << 16)); |
60 |
} |
61 |
slim_hidden_def (cairo_font_options_hash); |
62 |
@@ -328,6 +335,48 @@ |
63 |
} |
64 |
|
65 |
/** |
66 |
+ * _cairo_font_options_set_lcd_filter: |
67 |
+ * @options: a #cairo_font_options_t |
68 |
+ * @lcd_filter: the new LCD filter |
69 |
+ * |
70 |
+ * Sets the LCD filter for the font options object. The LCD filter |
71 |
+ * specifies how pixels are filtered when rendered with an antialiasing |
72 |
+ * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for |
73 |
+ * #cairo_lcd_filter_t for full details. |
74 |
+ * |
75 |
+ * Since: 1.8 |
76 |
+ **/ |
77 |
+void |
78 |
+_cairo_font_options_set_lcd_filter (cairo_font_options_t *options, |
79 |
+ cairo_lcd_filter_t lcd_filter) |
80 |
+{ |
81 |
+ if (cairo_font_options_status (options)) |
82 |
+ return; |
83 |
+ |
84 |
+ options->lcd_filter = lcd_filter; |
85 |
+} |
86 |
+ |
87 |
+/** |
88 |
+ * _cairo_font_options_get_lcd_filter: |
89 |
+ * @options: a #cairo_font_options_t |
90 |
+ * |
91 |
+ * Gets the LCD filter for the font options object. |
92 |
+ * See the documentation for #cairo_lcd_filter_t for full details. |
93 |
+ * |
94 |
+ * Return value: the LCD filter for the font options object |
95 |
+ * |
96 |
+ * Since: 1.8 |
97 |
+ **/ |
98 |
+cairo_lcd_filter_t |
99 |
+_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options) |
100 |
+{ |
101 |
+ if (cairo_font_options_status ((cairo_font_options_t *) options)) |
102 |
+ return CAIRO_LCD_FILTER_DEFAULT; |
103 |
+ |
104 |
+ return options->lcd_filter; |
105 |
+} |
106 |
+ |
107 |
+/** |
108 |
* cairo_font_options_set_hint_style: |
109 |
* @options: a #cairo_font_options_t |
110 |
* @hint_style: the new hint style |
111 |
diff -urNad cairo-1.8.0~/src/cairo-ft-font.c cairo-1.8.0/src/cairo-ft-font.c |
112 |
--- cairo-1.8.0~/src/cairo-ft-font.c 2008-09-25 22:28:24.000000000 +0200 |
113 |
+++ cairo-1.8.0/src/cairo-ft-font.c 2008-10-14 15:01:37.000000000 +0200 |
114 |
@@ -57,6 +57,30 @@ |
115 |
#include FT_SYNTHESIS_H |
116 |
#endif |
117 |
|
118 |
+#if HAVE_FT_LIBRARY_SETLCDFILTER |
119 |
+#include FT_LCD_FILTER_H |
120 |
+#endif |
121 |
+ |
122 |
+/* Fontconfig version older than 2.6 didn't have these options */ |
123 |
+#ifndef FC_LCD_FILTER |
124 |
+#define FC_LCD_FILTER "lcdfilter" |
125 |
+#endif |
126 |
+/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */ |
127 |
+#ifndef FC_LCD_NONE |
128 |
+#define FC_LCD_NONE 0 |
129 |
+#define FC_LCD_DEFAULT 1 |
130 |
+#define FC_LCD_LIGHT 2 |
131 |
+#define FC_LCD_LEGACY 3 |
132 |
+#endif |
133 |
+ |
134 |
+/* FreeType version older than 2.3.5(?) didn't have these options */ |
135 |
+#ifndef FT_LCD_FILTER_NONE |
136 |
+#define FT_LCD_FILTER_NONE 0 |
137 |
+#define FT_LCD_FILTER_DEFAULT 1 |
138 |
+#define FT_LCD_FILTER_LIGHT 2 |
139 |
+#define FT_LCD_FILTER_LEGACY 16 |
140 |
+#endif |
141 |
+ |
142 |
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) |
143 |
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) |
144 |
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) |
145 |
@@ -737,23 +761,286 @@ |
146 |
return CAIRO_STATUS_SUCCESS; |
147 |
} |
148 |
|
149 |
-/* Empirically-derived subpixel filtering values thanks to Keith |
150 |
- * Packard and libXft. */ |
151 |
-static const int filters[3][3] = { |
152 |
- /* red */ |
153 |
-#if 0 |
154 |
- { 65538*4/7,65538*2/7,65538*1/7 }, |
155 |
- /* green */ |
156 |
- { 65536*1/4, 65536*2/4, 65537*1/4 }, |
157 |
- /* blue */ |
158 |
- { 65538*1/7,65538*2/7,65538*4/7 }, |
159 |
+/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot |
160 |
+ * into a different format. For example, we want to convert a |
161 |
+ * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit |
162 |
+ * ARGB or ABGR bitmap. |
163 |
+ * |
164 |
+ * this function prepares a target descriptor for this operation. |
165 |
+ * |
166 |
+ * input :: target bitmap descriptor. The function will set its |
167 |
+ * 'width', 'rows' and 'pitch' fields, and only these |
168 |
+ * |
169 |
+ * slot :: the glyph slot containing the source bitmap. this |
170 |
+ * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP |
171 |
+ * |
172 |
+ * mode :: the requested final rendering mode. supported values are |
173 |
+ * MONO, NORMAL (i.e. gray), LCD and LCD_V |
174 |
+ * |
175 |
+ * the function returns the size in bytes of the corresponding buffer, |
176 |
+ * it's up to the caller to allocate the corresponding memory block |
177 |
+ * before calling _fill_xrender_bitmap |
178 |
+ * |
179 |
+ * it also returns -1 in case of error (e.g. incompatible arguments, |
180 |
+ * like trying to convert a gray bitmap into a monochrome one) |
181 |
+ */ |
182 |
+static int |
183 |
+_compute_xrender_bitmap_size(FT_Bitmap *target, |
184 |
+ FT_GlyphSlot slot, |
185 |
+ FT_Render_Mode mode) |
186 |
+{ |
187 |
+ FT_Bitmap *ftbit; |
188 |
+ int width, height, pitch; |
189 |
+ |
190 |
+ if (slot->format != FT_GLYPH_FORMAT_BITMAP) |
191 |
+ return -1; |
192 |
+ |
193 |
+ /* compute the size of the final bitmap */ |
194 |
+ ftbit = &slot->bitmap; |
195 |
+ |
196 |
+ width = ftbit->width; |
197 |
+ height = ftbit->rows; |
198 |
+ pitch = (width + 3) & ~3; |
199 |
+ |
200 |
+ switch (ftbit->pixel_mode) { |
201 |
+ case FT_PIXEL_MODE_MONO: |
202 |
+ if (mode == FT_RENDER_MODE_MONO) { |
203 |
+ pitch = (((width + 31) & ~31) >> 3); |
204 |
+ break; |
205 |
+ } |
206 |
+ /* fall-through */ |
207 |
+ |
208 |
+ case FT_PIXEL_MODE_GRAY: |
209 |
+ if (mode == FT_RENDER_MODE_LCD || |
210 |
+ mode == FT_RENDER_MODE_LCD_V) |
211 |
+ { |
212 |
+ /* each pixel is replicated into a 32-bit ARGB value */ |
213 |
+ pitch = width * 4; |
214 |
+ } |
215 |
+ break; |
216 |
+ |
217 |
+ case FT_PIXEL_MODE_LCD: |
218 |
+ if (mode != FT_RENDER_MODE_LCD) |
219 |
+ return -1; |
220 |
+ |
221 |
+ /* horz pixel triplets are packed into 32-bit ARGB values */ |
222 |
+ width /= 3; |
223 |
+ pitch = width * 4; |
224 |
+ break; |
225 |
+ |
226 |
+ case FT_PIXEL_MODE_LCD_V: |
227 |
+ if (mode != FT_RENDER_MODE_LCD_V) |
228 |
+ return -1; |
229 |
+ |
230 |
+ /* vert pixel triplets are packed into 32-bit ARGB values */ |
231 |
+ height /= 3; |
232 |
+ pitch = width * 4; |
233 |
+ break; |
234 |
+ |
235 |
+ default: /* unsupported source format */ |
236 |
+ return -1; |
237 |
+ } |
238 |
+ |
239 |
+ target->width = width; |
240 |
+ target->rows = height; |
241 |
+ target->pitch = pitch; |
242 |
+ target->buffer = NULL; |
243 |
+ |
244 |
+ return pitch * height; |
245 |
+} |
246 |
+ |
247 |
+/* this functions converts the glyph bitmap found in a FT_GlyphSlot |
248 |
+ * into a different format (see _compute_xrender_bitmap_size) |
249 |
+ * |
250 |
+ * you should call this function after _compute_xrender_bitmap_size |
251 |
+ * |
252 |
+ * target :: target bitmap descriptor. Note that its 'buffer' pointer |
253 |
+ * must point to memory allocated by the caller |
254 |
+ * |
255 |
+ * slot :: the glyph slot containing the source bitmap |
256 |
+ * |
257 |
+ * mode :: the requested final rendering mode |
258 |
+ * |
259 |
+ * bgr :: boolean, set if BGR or VBGR pixel ordering is needed |
260 |
+ */ |
261 |
+static void |
262 |
+_fill_xrender_bitmap(FT_Bitmap *target, |
263 |
+ FT_GlyphSlot slot, |
264 |
+ FT_Render_Mode mode, |
265 |
+ int bgr) |
266 |
+{ |
267 |
+ FT_Bitmap *ftbit = &slot->bitmap; |
268 |
+ unsigned char *srcLine = ftbit->buffer; |
269 |
+ unsigned char *dstLine = target->buffer; |
270 |
+ int src_pitch = ftbit->pitch; |
271 |
+ int width = target->width; |
272 |
+ int height = target->rows; |
273 |
+ int pitch = target->pitch; |
274 |
+ int subpixel; |
275 |
+ int h; |
276 |
+ |
277 |
+ subpixel = (mode == FT_RENDER_MODE_LCD || |
278 |
+ mode == FT_RENDER_MODE_LCD_V); |
279 |
+ |
280 |
+ if (src_pitch < 0) |
281 |
+ srcLine -= src_pitch * (ftbit->rows - 1); |
282 |
+ |
283 |
+ target->pixel_mode = ftbit->pixel_mode; |
284 |
+ |
285 |
+ switch (ftbit->pixel_mode) { |
286 |
+ case FT_PIXEL_MODE_MONO: |
287 |
+ if (subpixel) { |
288 |
+ /* convert mono to ARGB32 values */ |
289 |
+ |
290 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { |
291 |
+ int x; |
292 |
+ |
293 |
+ for (x = 0; x < width; x++) { |
294 |
+ if (srcLine[(x >> 3)] & (0x80 >> (x & 7))) |
295 |
+ ((unsigned int *) dstLine)[x] = 0xffffffffU; |
296 |
+ } |
297 |
+ } |
298 |
+ target->pixel_mode = FT_PIXEL_MODE_LCD; |
299 |
+ |
300 |
+ } else if (mode == FT_RENDER_MODE_NORMAL) { |
301 |
+ /* convert mono to 8-bit gray */ |
302 |
+ |
303 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { |
304 |
+ int x; |
305 |
+ |
306 |
+ for (x = 0; x < width; x++) { |
307 |
+ if (srcLine[(x >> 3)] & (0x80 >> (x & 7))) |
308 |
+ dstLine[x] = 0xff; |
309 |
+ } |
310 |
+ } |
311 |
+ target->pixel_mode = FT_PIXEL_MODE_GRAY; |
312 |
+ |
313 |
+ } else { |
314 |
+ /* copy mono to mono */ |
315 |
+ |
316 |
+ int bytes = (width + 7) >> 3; |
317 |
+ |
318 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) |
319 |
+ memcpy (dstLine, srcLine, bytes); |
320 |
+ } |
321 |
+ break; |
322 |
+ |
323 |
+ case FT_PIXEL_MODE_GRAY: |
324 |
+ if (subpixel) { |
325 |
+ /* convert gray to ARGB32 values */ |
326 |
+ |
327 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { |
328 |
+ int x; |
329 |
+ unsigned int *dst = (unsigned int *) dstLine; |
330 |
+ |
331 |
+ for (x = 0; x < width; x++) { |
332 |
+ unsigned int pix = srcLine[x]; |
333 |
+ |
334 |
+ pix |= (pix << 8); |
335 |
+ pix |= (pix << 16); |
336 |
+ |
337 |
+ dst[x] = pix; |
338 |
+ } |
339 |
+ } |
340 |
+ target->pixel_mode = FT_PIXEL_MODE_LCD; |
341 |
+ } else { |
342 |
+ /* copy gray into gray */ |
343 |
+ |
344 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) |
345 |
+ memcpy (dstLine, srcLine, width); |
346 |
+ } |
347 |
+ break; |
348 |
+ |
349 |
+ case FT_PIXEL_MODE_LCD: |
350 |
+ if (!bgr) { |
351 |
+ /* convert horizontal RGB into ARGB32 */ |
352 |
+ |
353 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { |
354 |
+ int x; |
355 |
+ unsigned char *src = srcLine; |
356 |
+ unsigned int *dst = (unsigned int *) dstLine; |
357 |
+ |
358 |
+ for (x = 0; x < width; x++, src += 3) { |
359 |
+ unsigned int pix; |
360 |
+ |
361 |
+ pix = ((unsigned int)src[0] << 16) | |
362 |
+ ((unsigned int)src[1] << 8) | |
363 |
+ ((unsigned int)src[2] ) | |
364 |
+ ((unsigned int)src[1] << 24) ; |
365 |
+ |
366 |
+ dst[x] = pix; |
367 |
+ } |
368 |
+ } |
369 |
+ } else { |
370 |
+ /* convert horizontal BGR into ARGB32 */ |
371 |
+ |
372 |
+ for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) { |
373 |
+ |
374 |
+ int x; |
375 |
+ unsigned char *src = srcLine; |
376 |
+ unsigned int *dst = (unsigned int *) dstLine; |
377 |
+ |
378 |
+ for (x = 0; x < width; x++, src += 3) { |
379 |
+ unsigned int pix; |
380 |
+ |
381 |
+ pix = ((unsigned int)src[2] << 16) | |
382 |
+ ((unsigned int)src[1] << 8) | |
383 |
+ ((unsigned int)src[0] ) | |
384 |
+ ((unsigned int)src[1] << 24) ; |
385 |
+ |
386 |
+ dst[x] = pix; |
387 |
+ } |
388 |
+ } |
389 |
+ } |
390 |
+ break; |
391 |
+ |
392 |
+ default: /* FT_PIXEL_MODE_LCD_V */ |
393 |
+ /* convert vertical RGB into ARGB32 */ |
394 |
+ if (!bgr) { |
395 |
+ |
396 |
+ for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) { |
397 |
+ int x; |
398 |
+ unsigned char* src = srcLine; |
399 |
+ unsigned int* dst = (unsigned int *) dstLine; |
400 |
+ |
401 |
+ for (x = 0; x < width; x++, src += 1) { |
402 |
+ unsigned int pix; |
403 |
+#if 1 |
404 |
+ pix = ((unsigned int)src[0] << 16) | |
405 |
+ ((unsigned int)src[src_pitch] << 8) | |
406 |
+ ((unsigned int)src[src_pitch*2] ) | |
407 |
+ 0xFF000000 ; |
408 |
+#else |
409 |
+ pix = ((unsigned int)src[0] << 16) | |
410 |
+ ((unsigned int)src[src_pitch] << 8) | |
411 |
+ ((unsigned int)src[src_pitch*2] ) | |
412 |
+ ((unsigned int)src[src_pitch] << 24) ; |
413 |
#endif |
414 |
- { 65538*9/13,65538*3/13,65538*1/13 }, |
415 |
- /* green */ |
416 |
- { 65538*1/6, 65538*4/6, 65538*1/6 }, |
417 |
- /* blue */ |
418 |
- { 65538*1/13,65538*3/13,65538*9/13 }, |
419 |
-}; |
420 |
+ dst[x] = pix; |
421 |
+ } |
422 |
+ } |
423 |
+ } else { |
424 |
+ |
425 |
+ for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) { |
426 |
+ int x; |
427 |
+ unsigned char *src = srcLine; |
428 |
+ unsigned int *dst = (unsigned int *) dstLine; |
429 |
+ |
430 |
+ for (x = 0; x < width; x++, src += 1) { |
431 |
+ unsigned int pix; |
432 |
+ |
433 |
+ pix = ((unsigned int)src[src_pitch * 2] << 16) | |
434 |
+ ((unsigned int)src[src_pitch] << 8) | |
435 |
+ ((unsigned int)src[0] ) | |
436 |
+ ((unsigned int)src[src_pitch] << 24) ; |
437 |
+ |
438 |
+ dst[x] = pix; |
439 |
+ } |
440 |
+ } |
441 |
+ } |
442 |
+ } |
443 |
+} |
444 |
+ |
445 |
|
446 |
/* Fills in val->image with an image surface created from @bitmap |
447 |
*/ |
448 |
@@ -766,7 +1053,7 @@ |
449 |
int width, height, stride; |
450 |
unsigned char *data; |
451 |
int format = CAIRO_FORMAT_A8; |
452 |
- cairo_bool_t subpixel = FALSE; |
453 |
+ cairo_image_surface_t *image; |
454 |
|
455 |
width = bitmap->width; |
456 |
height = bitmap->rows; |
457 |
@@ -823,11 +1110,7 @@ |
458 |
case FT_PIXEL_MODE_LCD: |
459 |
case FT_PIXEL_MODE_LCD_V: |
460 |
case FT_PIXEL_MODE_GRAY: |
461 |
- switch (font_options->antialias) { |
462 |
- case CAIRO_ANTIALIAS_DEFAULT: |
463 |
- case CAIRO_ANTIALIAS_GRAY: |
464 |
- case CAIRO_ANTIALIAS_NONE: |
465 |
- default: |
466 |
+ if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) { |
467 |
stride = bitmap->pitch; |
468 |
if (own_buffer) { |
469 |
data = bitmap->buffer; |
470 |
@@ -839,104 +1122,16 @@ |
471 |
memcpy (data, bitmap->buffer, stride * height); |
472 |
} |
473 |
format = CAIRO_FORMAT_A8; |
474 |
- break; |
475 |
- case CAIRO_ANTIALIAS_SUBPIXEL: { |
476 |
- int x, y; |
477 |
- unsigned char *in_line, *out_line, *in; |
478 |
- unsigned int *out; |
479 |
- unsigned int red, green, blue; |
480 |
- int rf, gf, bf; |
481 |
- int s; |
482 |
- int o, os; |
483 |
- unsigned char *data_rgba; |
484 |
- unsigned int width_rgba, stride_rgba; |
485 |
- int vmul = 1; |
486 |
- int hmul = 1; |
487 |
+ } else { |
488 |
+ /* if we get there, the data from the source bitmap |
489 |
+ * really comes from _fill_xrender_bitmap, and is |
490 |
+ * made of 32-bit ARGB or ABGR values */ |
491 |
+ assert (own_buffer != 0); |
492 |
+ assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); |
493 |
|
494 |
- switch (font_options->subpixel_order) { |
495 |
- case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
496 |
- case CAIRO_SUBPIXEL_ORDER_RGB: |
497 |
- case CAIRO_SUBPIXEL_ORDER_BGR: |
498 |
- default: |
499 |
- width /= 3; |
500 |
- hmul = 3; |
501 |
- break; |
502 |
- case CAIRO_SUBPIXEL_ORDER_VRGB: |
503 |
- case CAIRO_SUBPIXEL_ORDER_VBGR: |
504 |
- vmul = 3; |
505 |
- height /= 3; |
506 |
- break; |
507 |
- } |
508 |
- /* |
509 |
- * Filter the glyph to soften the color fringes |
510 |
- */ |
511 |
- width_rgba = width; |
512 |
+ data = bitmap->buffer; |
513 |
stride = bitmap->pitch; |
514 |
- stride_rgba = (width_rgba * 4 + 3) & ~3; |
515 |
- data_rgba = calloc (stride_rgba, height); |
516 |
- if (data_rgba == NULL) { |
517 |
- if (own_buffer) |
518 |
- free (bitmap->buffer); |
519 |
- return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
520 |
- } |
521 |
- |
522 |
- os = 1; |
523 |
- switch (font_options->subpixel_order) { |
524 |
- case CAIRO_SUBPIXEL_ORDER_VRGB: |
525 |
- os = stride; |
526 |
- case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
527 |
- case CAIRO_SUBPIXEL_ORDER_RGB: |
528 |
- default: |
529 |
- rf = 0; |
530 |
- gf = 1; |
531 |
- bf = 2; |
532 |
- break; |
533 |
- case CAIRO_SUBPIXEL_ORDER_VBGR: |
534 |
- os = stride; |
535 |
- case CAIRO_SUBPIXEL_ORDER_BGR: |
536 |
- bf = 0; |
537 |
- gf = 1; |
538 |
- rf = 2; |
539 |
- break; |
540 |
- } |
541 |
- in_line = bitmap->buffer; |
542 |
- out_line = data_rgba; |
543 |
- for (y = 0; y < height; y++) |
544 |
- { |
545 |
- in = in_line; |
546 |
- out = (unsigned int *) out_line; |
547 |
- in_line += stride * vmul; |
548 |
- out_line += stride_rgba; |
549 |
- for (x = 0; x < width * hmul; x += hmul) |
550 |
- { |
551 |
- red = green = blue = 0; |
552 |
- o = 0; |
553 |
- for (s = 0; s < 3; s++) |
554 |
- { |
555 |
- red += filters[rf][s]*in[x+o]; |
556 |
- green += filters[gf][s]*in[x+o]; |
557 |
- blue += filters[bf][s]*in[x+o]; |
558 |
- o += os; |
559 |
- } |
560 |
- red = red / 65536; |
561 |
- green = green / 65536; |
562 |
- blue = blue / 65536; |
563 |
- *out++ = (green << 24) | (red << 16) | (green << 8) | blue; |
564 |
- } |
565 |
- } |
566 |
- |
567 |
- /* Images here are stored in native format. The |
568 |
- * backend must convert to its own format as needed |
569 |
- */ |
570 |
- |
571 |
- if (own_buffer) |
572 |
- free (bitmap->buffer); |
573 |
- data = data_rgba; |
574 |
- stride = stride_rgba; |
575 |
format = CAIRO_FORMAT_ARGB32; |
576 |
- subpixel = TRUE; |
577 |
- break; |
578 |
- } |
579 |
} |
580 |
break; |
581 |
case FT_PIXEL_MODE_GRAY2: |
582 |
@@ -948,19 +1143,20 @@ |
583 |
return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
584 |
} |
585 |
|
586 |
- *surface = (cairo_image_surface_t *) |
587 |
+ /* XXX */ |
588 |
+ *surface = image = (cairo_image_surface_t *) |
589 |
cairo_image_surface_create_for_data (data, |
590 |
format, |
591 |
width, height, stride); |
592 |
- if ((*surface)->base.status) { |
593 |
+ if (image->base.status) { |
594 |
free (data); |
595 |
return (*surface)->base.status; |
596 |
} |
597 |
|
598 |
- if (subpixel) |
599 |
- pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); |
600 |
+ if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) |
601 |
+ pixman_image_set_component_alpha (image->pixman_image, TRUE); |
602 |
|
603 |
- _cairo_image_surface_assume_ownership_of_data ((*surface)); |
604 |
+ _cairo_image_surface_assume_ownership_of_data (image); |
605 |
|
606 |
return CAIRO_STATUS_SUCCESS; |
607 |
} |
608 |
@@ -985,16 +1181,59 @@ |
609 |
cairo_font_options_t *font_options, |
610 |
cairo_image_surface_t **surface) |
611 |
{ |
612 |
+ int rgba = FC_RGBA_UNKNOWN; |
613 |
+ int lcd_filter = FT_LCD_FILTER_LEGACY; |
614 |
FT_GlyphSlot glyphslot = face->glyph; |
615 |
FT_Outline *outline = &glyphslot->outline; |
616 |
FT_Bitmap bitmap; |
617 |
FT_BBox cbox; |
618 |
- FT_Matrix matrix; |
619 |
- int hmul = 1; |
620 |
- int vmul = 1; |
621 |
- unsigned int width, height, stride; |
622 |
- cairo_bool_t subpixel = FALSE; |
623 |
+ unsigned int width, height; |
624 |
cairo_status_t status; |
625 |
+ FT_Error fterror; |
626 |
+ FT_Library library = glyphslot->library; |
627 |
+ FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL; |
628 |
+ |
629 |
+ switch (font_options->antialias) { |
630 |
+ case CAIRO_ANTIALIAS_NONE: |
631 |
+ render_mode = FT_RENDER_MODE_MONO; |
632 |
+ break; |
633 |
+ |
634 |
+ case CAIRO_ANTIALIAS_SUBPIXEL: |
635 |
+ switch (font_options->subpixel_order) { |
636 |
+ case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
637 |
+ case CAIRO_SUBPIXEL_ORDER_RGB: |
638 |
+ case CAIRO_SUBPIXEL_ORDER_BGR: |
639 |
+ render_mode = FT_RENDER_MODE_LCD; |
640 |
+ break; |
641 |
+ |
642 |
+ case CAIRO_SUBPIXEL_ORDER_VRGB: |
643 |
+ case CAIRO_SUBPIXEL_ORDER_VBGR: |
644 |
+ render_mode = FT_RENDER_MODE_LCD_V; |
645 |
+ break; |
646 |
+ } |
647 |
+ |
648 |
+ switch (font_options->lcd_filter) { |
649 |
+ case CAIRO_LCD_FILTER_NONE: |
650 |
+ lcd_filter = FT_LCD_FILTER_NONE; |
651 |
+ break; |
652 |
+ case CAIRO_LCD_FILTER_DEFAULT: |
653 |
+ case CAIRO_LCD_FILTER_INTRA_PIXEL: |
654 |
+ lcd_filter = FT_LCD_FILTER_LEGACY; |
655 |
+ break; |
656 |
+ case CAIRO_LCD_FILTER_FIR3: |
657 |
+ lcd_filter = FT_LCD_FILTER_LIGHT; |
658 |
+ break; |
659 |
+ case CAIRO_LCD_FILTER_FIR5: |
660 |
+ lcd_filter = FT_LCD_FILTER_DEFAULT; |
661 |
+ break; |
662 |
+ } |
663 |
+ |
664 |
+ break; |
665 |
+ |
666 |
+ case CAIRO_ANTIALIAS_DEFAULT: |
667 |
+ case CAIRO_ANTIALIAS_GRAY: |
668 |
+ render_mode = FT_RENDER_MODE_NORMAL; |
669 |
+ } |
670 |
|
671 |
FT_Outline_Get_CBox (outline, &cbox); |
672 |
|
673 |
@@ -1005,20 +1244,21 @@ |
674 |
|
675 |
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); |
676 |
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); |
677 |
- stride = (width * hmul + 3) & ~3; |
678 |
|
679 |
if (width * height == 0) { |
680 |
cairo_format_t format; |
681 |
/* Looks like fb handles zero-sized images just fine */ |
682 |
- switch (font_options->antialias) { |
683 |
- case CAIRO_ANTIALIAS_NONE: |
684 |
+ switch (render_mode) { |
685 |
+ case FT_RENDER_MODE_MONO: |
686 |
format = CAIRO_FORMAT_A1; |
687 |
break; |
688 |
- case CAIRO_ANTIALIAS_SUBPIXEL: |
689 |
+ case FT_RENDER_MODE_LCD: |
690 |
+ case FT_RENDER_MODE_LCD_V: |
691 |
format= CAIRO_FORMAT_ARGB32; |
692 |
break; |
693 |
- case CAIRO_ANTIALIAS_DEFAULT: |
694 |
- case CAIRO_ANTIALIAS_GRAY: |
695 |
+ case FT_RENDER_MODE_LIGHT: |
696 |
+ case FT_RENDER_MODE_NORMAL: |
697 |
+ case FT_RENDER_MODE_MAX: |
698 |
default: |
699 |
format = CAIRO_FORMAT_A8; |
700 |
break; |
701 |
@@ -1030,73 +1270,73 @@ |
702 |
return (*surface)->base.status; |
703 |
} else { |
704 |
|
705 |
- matrix.xx = matrix.yy = 0x10000L; |
706 |
- matrix.xy = matrix.yx = 0; |
707 |
+ int bitmap_size; |
708 |
|
709 |
- switch (font_options->antialias) { |
710 |
- case CAIRO_ANTIALIAS_NONE: |
711 |
- bitmap.pixel_mode = FT_PIXEL_MODE_MONO; |
712 |
- bitmap.num_grays = 1; |
713 |
- stride = ((width + 31) & -32) >> 3; |
714 |
- break; |
715 |
- case CAIRO_ANTIALIAS_DEFAULT: |
716 |
- case CAIRO_ANTIALIAS_GRAY: |
717 |
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; |
718 |
- bitmap.num_grays = 256; |
719 |
- stride = (width + 3) & -4; |
720 |
+ switch (render_mode) { |
721 |
+ case FT_RENDER_MODE_LCD: |
722 |
+ if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) { |
723 |
+ rgba = FC_RGBA_BGR; |
724 |
+ } else { |
725 |
+ rgba = FC_RGBA_RGB; |
726 |
+ } |
727 |
break; |
728 |
- case CAIRO_ANTIALIAS_SUBPIXEL: |
729 |
- switch (font_options->subpixel_order) { |
730 |
- case CAIRO_SUBPIXEL_ORDER_RGB: |
731 |
- case CAIRO_SUBPIXEL_ORDER_BGR: |
732 |
- case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
733 |
- default: |
734 |
- matrix.xx *= 3; |
735 |
- hmul = 3; |
736 |
- subpixel = TRUE; |
737 |
- break; |
738 |
- case CAIRO_SUBPIXEL_ORDER_VRGB: |
739 |
- case CAIRO_SUBPIXEL_ORDER_VBGR: |
740 |
- matrix.yy *= 3; |
741 |
- vmul = 3; |
742 |
- subpixel = TRUE; |
743 |
- break; |
744 |
+ case FT_RENDER_MODE_LCD_V: |
745 |
+ if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) { |
746 |
+ rgba = FC_RGBA_VBGR; |
747 |
+ } else { |
748 |
+ rgba = FC_RGBA_VRGB; |
749 |
} |
750 |
- FT_Outline_Transform (outline, &matrix); |
751 |
- |
752 |
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; |
753 |
- bitmap.num_grays = 256; |
754 |
- stride = (width * hmul + 3) & -4; |
755 |
+ break; |
756 |
+ case FT_RENDER_MODE_MONO: |
757 |
+ case FT_RENDER_MODE_LIGHT: |
758 |
+ case FT_RENDER_MODE_NORMAL: |
759 |
+ case FT_RENDER_MODE_MAX: |
760 |
+ default: |
761 |
+ break; |
762 |
} |
763 |
|
764 |
- bitmap.pitch = stride; |
765 |
- bitmap.width = width * hmul; |
766 |
- bitmap.rows = height * vmul; |
767 |
- bitmap.buffer = calloc (stride, bitmap.rows); |
768 |
- if (bitmap.buffer == NULL) |
769 |
+#if HAVE_FT_LIBRARY_SETLCDFILTER |
770 |
+ FT_Library_SetLcdFilter (library, lcd_filter); |
771 |
+#endif |
772 |
+ |
773 |
+ fterror = FT_Render_Glyph (face->glyph, render_mode); |
774 |
+ |
775 |
+#if HAVE_FT_LIBRARY_SETLCDFILTER |
776 |
+ FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE); |
777 |
+#endif |
778 |
+ |
779 |
+ if (fterror != 0) |
780 |
return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
781 |
|
782 |
- FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); |
783 |
+ bitmap_size = _compute_xrender_bitmap_size (&bitmap, |
784 |
+ face->glyph, |
785 |
+ render_mode); |
786 |
+ if (bitmap_size < 0) |
787 |
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
788 |
|
789 |
- if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { |
790 |
- free (bitmap.buffer); |
791 |
+ bitmap.buffer = calloc (1, bitmap_size); |
792 |
+ if (bitmap.buffer == NULL) |
793 |
return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
794 |
- } |
795 |
|
796 |
+ _fill_xrender_bitmap (&bitmap, face->glyph, render_mode, |
797 |
+ (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR)); |
798 |
+ |
799 |
+ /* Note: |
800 |
+ * _get_bitmap_surface will free bitmap.buffer if there is an error |
801 |
+ */ |
802 |
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); |
803 |
if (status) |
804 |
return status; |
805 |
- } |
806 |
|
807 |
- /* |
808 |
- * Note: the font's coordinate system is upside down from ours, so the |
809 |
- * Y coordinate of the control box needs to be negated. Moreover, device |
810 |
- * offsets are position of glyph origin relative to top left while xMin |
811 |
- * and yMax are offsets of top left relative to origin. Another negation. |
812 |
- */ |
813 |
- cairo_surface_set_device_offset (&(*surface)->base, |
814 |
- floor (-(double) cbox.xMin / 64.0), |
815 |
- floor (+(double) cbox.yMax / 64.0)); |
816 |
+ /* Note: the font's coordinate system is upside down from ours, so the |
817 |
+ * Y coordinate of the control box needs to be negated. Moreover, device |
818 |
+ * offsets are position of glyph origin relative to top left while xMin |
819 |
+ * and yMax are offsets of top left relative to origin. Another negation. |
820 |
+ */ |
821 |
+ cairo_surface_set_device_offset (&(*surface)->base, |
822 |
+ (double)-glyphslot->bitmap_left, |
823 |
+ (double)+glyphslot->bitmap_top); |
824 |
+ } |
825 |
|
826 |
return CAIRO_STATUS_SUCCESS; |
827 |
} |
828 |
@@ -1316,6 +1556,7 @@ |
829 |
|
830 |
if (antialias) { |
831 |
cairo_subpixel_order_t subpixel_order; |
832 |
+ int lcd_filter; |
833 |
|
834 |
/* disable hinting if requested */ |
835 |
if (FcPatternGetBool (pattern, |
836 |
@@ -1351,6 +1592,25 @@ |
837 |
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; |
838 |
} |
839 |
|
840 |
+ if (FcPatternGetInteger (pattern, |
841 |
+ FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch) |
842 |
+ { |
843 |
+ switch (lcd_filter) { |
844 |
+ case FC_LCD_NONE: |
845 |
+ ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE; |
846 |
+ break; |
847 |
+ case FC_LCD_DEFAULT: |
848 |
+ ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5; |
849 |
+ break; |
850 |
+ case FC_LCD_LIGHT: |
851 |
+ ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3; |
852 |
+ break; |
853 |
+ case FC_LCD_LEGACY: |
854 |
+ ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL; |
855 |
+ break; |
856 |
+ } |
857 |
+ } |
858 |
+ |
859 |
#ifdef FC_HINT_STYLE |
860 |
if (FcPatternGetInteger (pattern, |
861 |
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) |
862 |
@@ -1451,6 +1711,12 @@ |
863 |
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE) |
864 |
options->base.hint_style = CAIRO_HINT_STYLE_NONE; |
865 |
|
866 |
+ if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT) |
867 |
+ options->base.lcd_filter = other->base.lcd_filter; |
868 |
+ |
869 |
+ if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE) |
870 |
+ options->base.lcd_filter = CAIRO_LCD_FILTER_NONE; |
871 |
+ |
872 |
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { |
873 |
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE) |
874 |
load_flags |= FT_LOAD_NO_HINTING; |
875 |
@@ -1474,11 +1740,11 @@ |
876 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
877 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
878 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
879 |
- load_target |= FT_LOAD_TARGET_LCD; |
880 |
+ load_target = FT_LOAD_TARGET_LCD; |
881 |
break; |
882 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
883 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
884 |
- load_target |= FT_LOAD_TARGET_LCD_V; |
885 |
+ load_target = FT_LOAD_TARGET_LCD_V; |
886 |
break; |
887 |
} |
888 |
} |
889 |
@@ -2421,6 +2687,34 @@ |
890 |
} |
891 |
} |
892 |
|
893 |
+ if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT) |
894 |
+ { |
895 |
+ if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch) |
896 |
+ { |
897 |
+ int lcd_filter; |
898 |
+ |
899 |
+ switch (options->lcd_filter) { |
900 |
+ case CAIRO_LCD_FILTER_NONE: |
901 |
+ lcd_filter = FT_LCD_FILTER_NONE; |
902 |
+ break; |
903 |
+ case CAIRO_LCD_FILTER_DEFAULT: |
904 |
+ case CAIRO_LCD_FILTER_INTRA_PIXEL: |
905 |
+ lcd_filter = FT_LCD_FILTER_LEGACY; |
906 |
+ break; |
907 |
+ case CAIRO_LCD_FILTER_FIR3: |
908 |
+ lcd_filter = FT_LCD_FILTER_LIGHT; |
909 |
+ break; |
910 |
+ default: |
911 |
+ case CAIRO_LCD_FILTER_FIR5: |
912 |
+ lcd_filter = FT_LCD_FILTER_DEFAULT; |
913 |
+ break; |
914 |
+ } |
915 |
+ |
916 |
+ if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter)) |
917 |
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
918 |
+ } |
919 |
+ } |
920 |
+ |
921 |
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT) |
922 |
{ |
923 |
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) |
924 |
diff -urNad cairo-1.8.0~/src/cairo-surface.c cairo-1.8.0/src/cairo-surface.c |
925 |
--- cairo-1.8.0~/src/cairo-surface.c 2008-09-25 22:28:56.000000000 +0200 |
926 |
+++ cairo-1.8.0/src/cairo-surface.c 2008-10-14 15:01:37.000000000 +0200 |
927 |
@@ -73,6 +73,7 @@ |
928 |
FALSE, /* has_font_options */ \ |
929 |
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ |
930 |
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ |
931 |
+ CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \ |
932 |
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ |
933 |
CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \ |
934 |
} /* font_options */ \ |
935 |
diff -urNad cairo-1.8.0~/src/cairo-types-private.h cairo-1.8.0/src/cairo-types-private.h |
936 |
--- cairo-1.8.0~/src/cairo-types-private.h 2008-09-25 22:29:06.000000000 +0200 |
937 |
+++ cairo-1.8.0/src/cairo-types-private.h 2008-10-14 15:01:37.000000000 +0200 |
938 |
@@ -113,9 +113,35 @@ |
939 |
cairo_bool_t is_snapshot; |
940 |
}; |
941 |
|
942 |
+ |
943 |
+/** |
944 |
+ * cairo_lcd_filter_t: |
945 |
+ * @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for |
946 |
+ * font backend and target device |
947 |
+ * @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering |
948 |
+ * @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter |
949 |
+ * @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel |
950 |
+ * @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel |
951 |
+ * |
952 |
+ * The LCD filter specifies the low-pass filter applied to LCD-optimized |
953 |
+ * bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL. |
954 |
+ * |
955 |
+ * Note: This API was temporarily made available in the public |
956 |
+ * interface during the 1.7.x development series, but was made private |
957 |
+ * before 1.8. |
958 |
+ **/ |
959 |
+typedef enum _cairo_lcd_filter { |
960 |
+ CAIRO_LCD_FILTER_DEFAULT, |
961 |
+ CAIRO_LCD_FILTER_NONE, |
962 |
+ CAIRO_LCD_FILTER_INTRA_PIXEL, |
963 |
+ CAIRO_LCD_FILTER_FIR3, |
964 |
+ CAIRO_LCD_FILTER_FIR5 |
965 |
+} cairo_lcd_filter_t; |
966 |
+ |
967 |
struct _cairo_font_options { |
968 |
cairo_antialias_t antialias; |
969 |
cairo_subpixel_order_t subpixel_order; |
970 |
+ cairo_lcd_filter_t lcd_filter; |
971 |
cairo_hint_style_t hint_style; |
972 |
cairo_hint_metrics_t hint_metrics; |
973 |
}; |
974 |
diff -urNad cairo-1.8.0~/src/cairo-xlib-screen.c cairo-1.8.0/src/cairo-xlib-screen.c |
975 |
--- cairo-1.8.0~/src/cairo-xlib-screen.c 2008-09-25 22:29:39.000000000 +0200 |
976 |
+++ cairo-1.8.0/src/cairo-xlib-screen.c 2008-10-14 15:01:37.000000000 +0200 |
977 |
@@ -150,13 +150,22 @@ |
978 |
cairo_bool_t xft_antialias; |
979 |
int xft_hintstyle; |
980 |
int xft_rgba; |
981 |
+ int xft_lcdfilter; |
982 |
cairo_antialias_t antialias; |
983 |
cairo_subpixel_order_t subpixel_order; |
984 |
+ cairo_lcd_filter_t lcd_filter; |
985 |
cairo_hint_style_t hint_style; |
986 |
|
987 |
if (!get_boolean_default (dpy, "antialias", &xft_antialias)) |
988 |
xft_antialias = TRUE; |
989 |
|
990 |
+ if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) { |
991 |
+ /* -1 is an non-existant Fontconfig constant used to differentiate |
992 |
+ * the case when no lcdfilter property is available. |
993 |
+ */ |
994 |
+ xft_lcdfilter = -1; |
995 |
+ } |
996 |
+ |
997 |
if (!get_boolean_default (dpy, "hinting", &xft_hinting)) |
998 |
xft_hinting = TRUE; |
999 |
|
1000 |
@@ -239,6 +248,24 @@ |
1001 |
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; |
1002 |
} |
1003 |
|
1004 |
+ switch (xft_lcdfilter) { |
1005 |
+ case FC_LCD_NONE: |
1006 |
+ lcd_filter = CAIRO_LCD_FILTER_NONE; |
1007 |
+ break; |
1008 |
+ case FC_LCD_DEFAULT: |
1009 |
+ lcd_filter = CAIRO_LCD_FILTER_FIR5; |
1010 |
+ break; |
1011 |
+ case FC_LCD_LIGHT: |
1012 |
+ lcd_filter = CAIRO_LCD_FILTER_FIR3; |
1013 |
+ break; |
1014 |
+ case FC_LCD_LEGACY: |
1015 |
+ lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL; |
1016 |
+ break; |
1017 |
+ default: |
1018 |
+ lcd_filter = CAIRO_LCD_FILTER_DEFAULT; |
1019 |
+ break; |
1020 |
+ } |
1021 |
+ |
1022 |
if (xft_antialias) { |
1023 |
if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT) |
1024 |
antialias = CAIRO_ANTIALIAS_GRAY; |
1025 |
@@ -251,6 +278,7 @@ |
1026 |
cairo_font_options_set_hint_style (&info->font_options, hint_style); |
1027 |
cairo_font_options_set_antialias (&info->font_options, antialias); |
1028 |
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order); |
1029 |
+ _cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter); |
1030 |
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON); |
1031 |
} |
1032 |
|
1033 |
diff -urNad cairo-1.8.0~/src/cairoint.h cairo-1.8.0/src/cairoint.h |
1034 |
--- cairo-1.8.0~/src/cairoint.h 2008-09-26 00:56:48.000000000 +0200 |
1035 |
+++ cairo-1.8.0/src/cairoint.h 2008-10-14 15:01:37.000000000 +0200 |
1036 |
@@ -1336,6 +1336,13 @@ |
1037 |
_cairo_font_options_init_copy (cairo_font_options_t *options, |
1038 |
const cairo_font_options_t *other); |
1039 |
|
1040 |
+cairo_private void |
1041 |
+_cairo_font_options_set_lcd_filter (cairo_font_options_t *options, |
1042 |
+ cairo_lcd_filter_t lcd_filter); |
1043 |
+ |
1044 |
+cairo_private cairo_lcd_filter_t |
1045 |
+_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options); |
1046 |
+ |
1047 |
/* cairo-hull.c */ |
1048 |
cairo_private cairo_status_t |
1049 |
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices); |