]>
Commit | Line | Data |
---|---|---|
33282416 JB |
1 | --- cairo-1.4.12/src/cairo-ft-font.c.orig 2007-11-27 07:20:12.000000000 +0100 |
2 | +++ cairo-1.4.12/src/cairo-ft-font.c 2007-11-28 19:54:09.894901361 +0100 | |
bc624305 | 3 | @@ -55,6 +55,8 @@ |
6e13550b | 4 | #include FT_SYNTHESIS_H |
5 | #endif | |
6 | ||
7 | +#include FT_LCD_FILTER_H | |
8 | + | |
9 | #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) | |
10 | #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) | |
11 | #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) | |
33282416 | 12 | @@ -702,23 +704,300 @@ |
bc624305 | 13 | return CAIRO_STATUS_SUCCESS; |
6e13550b | 14 | } |
15 | ||
16 | -/* Empirically-derived subpixel filtering values thanks to Keith | |
17 | - * Packard and libXft. */ | |
18 | -static const int filters[3][3] = { | |
19 | - /* red */ | |
20 | -#if 0 | |
21 | - { 65538*4/7,65538*2/7,65538*1/7 }, | |
22 | - /* green */ | |
23 | - { 65536*1/4, 65536*2/4, 65537*1/4 }, | |
24 | - /* blue */ | |
25 | - { 65538*1/7,65538*2/7,65538*4/7 }, | |
26 | +/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot | |
27 | + * into a different format. For example, we want to convert a | |
28 | + * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit | |
29 | + * ARGB or ABGR bitmap. | |
30 | + * | |
31 | + * this function prepares a target descriptor for this operation. | |
32 | + * | |
33 | + * input :: target bitmap descriptor. The function will set its | |
34 | + * 'width', 'rows' and 'pitch' fields, and only these | |
35 | + * | |
36 | + * slot :: the glyph slot containing the source bitmap. this | |
37 | + * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP | |
38 | + * | |
39 | + * mode :: the requested final rendering mode. supported values are | |
40 | + * MONO, NORMAL (i.e. gray), LCD and LCD_V | |
41 | + * | |
42 | + * the function returns the size in bytes of the corresponding buffer, | |
43 | + * it's up to the caller to allocate the corresponding memory block | |
44 | + * before calling _fill_xrender_bitmap | |
45 | + * | |
46 | + * it also returns -1 in case of error (e.g. incompatible arguments, | |
47 | + * like trying to convert a gray bitmap into a monochrome one) | |
48 | + */ | |
49 | +static int | |
50 | +_compute_xrender_bitmap_size( FT_Bitmap* target, | |
51 | + FT_GlyphSlot slot, | |
52 | + FT_Render_Mode mode ) | |
53 | +{ | |
54 | + FT_Bitmap* ftbit; | |
55 | + int width, height, pitch; | |
56 | + | |
57 | + if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) | |
58 | + return -1; | |
59 | + | |
60 | + // compute the size of the final bitmap | |
61 | + ftbit = &slot->bitmap; | |
62 | + | |
63 | + width = ftbit->width; | |
64 | + height = ftbit->rows; | |
65 | + pitch = (width+3) & ~3; | |
66 | + | |
67 | + switch ( ftbit->pixel_mode ) | |
68 | + { | |
69 | + case FT_PIXEL_MODE_MONO: | |
70 | + if ( mode == FT_RENDER_MODE_MONO ) | |
71 | + { | |
72 | + pitch = (((width+31) & ~31) >> 3); | |
73 | + break; | |
74 | + } | |
75 | + /* fall-through */ | |
76 | + | |
77 | + case FT_PIXEL_MODE_GRAY: | |
78 | + if ( mode == FT_RENDER_MODE_LCD || | |
79 | + mode == FT_RENDER_MODE_LCD_V ) | |
80 | + { | |
81 | + /* each pixel is replicated into a 32-bit ARGB value */ | |
82 | + pitch = width*4; | |
83 | + } | |
84 | + break; | |
85 | + | |
86 | + case FT_PIXEL_MODE_LCD: | |
87 | + if ( mode != FT_RENDER_MODE_LCD ) | |
88 | + return -1; | |
89 | + | |
90 | + /* horz pixel triplets are packed into 32-bit ARGB values */ | |
91 | + width /= 3; | |
92 | + pitch = width*4; | |
93 | + break; | |
94 | + | |
95 | + case FT_PIXEL_MODE_LCD_V: | |
96 | + if ( mode != FT_RENDER_MODE_LCD_V ) | |
97 | + return -1; | |
98 | + | |
99 | + /* vert pixel triplets are packed into 32-bit ARGB values */ | |
100 | + height /= 3; | |
101 | + pitch = width*4; | |
102 | + break; | |
103 | + | |
104 | + default: /* unsupported source format */ | |
105 | + return -1; | |
106 | + } | |
107 | + | |
108 | + target->width = width; | |
109 | + target->rows = height; | |
110 | + target->pitch = pitch; | |
111 | + target->buffer = NULL; | |
112 | + | |
113 | + return pitch * height; | |
114 | +} | |
115 | + | |
116 | +/* this functions converts the glyph bitmap found in a FT_GlyphSlot | |
117 | + * into a different format (see _compute_xrender_bitmap_size) | |
118 | + * | |
119 | + * you should call this function after _compute_xrender_bitmap_size | |
120 | + * | |
121 | + * target :: target bitmap descriptor. Note that its 'buffer' pointer | |
122 | + * must point to memory allocated by the caller | |
123 | + * | |
124 | + * slot :: the glyph slot containing the source bitmap | |
125 | + * | |
126 | + * mode :: the requested final rendering mode | |
127 | + * | |
128 | + * bgr :: boolean, set if BGR or VBGR pixel ordering is needed | |
129 | + */ | |
130 | +static void | |
131 | +_fill_xrender_bitmap( FT_Bitmap* target, | |
132 | + FT_GlyphSlot slot, | |
133 | + FT_Render_Mode mode, | |
134 | + int bgr ) | |
135 | +{ | |
136 | + FT_Bitmap* ftbit = &slot->bitmap; | |
137 | + unsigned char* srcLine = ftbit->buffer; | |
138 | + unsigned char* dstLine = target->buffer; | |
139 | + int src_pitch = ftbit->pitch; | |
140 | + int width = target->width; | |
141 | + int height = target->rows; | |
142 | + int pitch = target->pitch; | |
143 | + int subpixel; | |
144 | + int h; | |
145 | + | |
146 | + subpixel = ( mode == FT_RENDER_MODE_LCD || | |
147 | + mode == FT_RENDER_MODE_LCD_V ); | |
148 | + | |
149 | + if ( src_pitch < 0 ) | |
150 | + srcLine -= src_pitch*(ftbit->rows-1); | |
151 | + | |
152 | + target->pixel_mode = ftbit->pixel_mode; | |
153 | + | |
154 | + switch ( ftbit->pixel_mode ) | |
155 | + { | |
156 | + case FT_PIXEL_MODE_MONO: | |
157 | + if ( subpixel ) /* convert mono to ARGB32 values */ | |
158 | + { | |
159 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
160 | + { | |
161 | + int x; | |
162 | + | |
163 | + for ( x = 0; x < width; x++ ) | |
164 | + { | |
165 | + if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) | |
166 | + ((unsigned int*)dstLine)[x] = 0xffffffffU; | |
167 | + } | |
168 | + } | |
169 | + target->pixel_mode = FT_PIXEL_MODE_LCD; | |
170 | + } | |
171 | + else if ( mode == FT_RENDER_MODE_NORMAL ) /* convert mono to 8-bit gray */ | |
172 | + { | |
173 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
174 | + { | |
175 | + int x; | |
176 | + | |
177 | + for ( x = 0; x < width; x++ ) | |
178 | + { | |
179 | + if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) | |
180 | + dstLine[x] = 0xff; | |
181 | + } | |
182 | + } | |
183 | + target->pixel_mode = FT_PIXEL_MODE_GRAY; | |
184 | + } | |
185 | + else /* copy mono to mono */ | |
186 | + { | |
187 | + int bytes = (width+7) >> 3; | |
188 | + | |
189 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
190 | + memcpy( dstLine, srcLine, bytes ); | |
191 | + } | |
192 | + break; | |
193 | + | |
194 | + case FT_PIXEL_MODE_GRAY: | |
195 | + if ( subpixel ) /* convert gray to ARGB32 values */ | |
196 | + { | |
197 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
198 | + { | |
199 | + int x; | |
200 | + unsigned int* dst = (unsigned int*)dstLine; | |
201 | + | |
202 | + for ( x = 0; x < width; x++ ) | |
203 | + { | |
204 | + unsigned int pix = srcLine[x]; | |
205 | + | |
206 | + pix |= (pix << 8); | |
207 | + pix |= (pix << 16); | |
208 | + | |
209 | + dst[x] = pix; | |
210 | + } | |
211 | + } | |
212 | + target->pixel_mode = FT_PIXEL_MODE_LCD; | |
213 | + } | |
214 | + else /* copy gray into gray */ | |
215 | + { | |
216 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
217 | + memcpy( dstLine, srcLine, width ); | |
218 | + } | |
219 | + break; | |
220 | + | |
221 | + case FT_PIXEL_MODE_LCD: | |
222 | + if ( !bgr ) | |
223 | + { | |
224 | + /* convert horizontal RGB into ARGB32 */ | |
225 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
226 | + { | |
227 | + int x; | |
228 | + unsigned char* src = srcLine; | |
229 | + unsigned int* dst = (unsigned int*)dstLine; | |
230 | + | |
231 | + for ( x = 0; x < width; x++, src += 3 ) | |
232 | + { | |
233 | + unsigned int pix; | |
234 | + | |
235 | + pix = ((unsigned int)src[0] << 16) | | |
236 | + ((unsigned int)src[1] << 8) | | |
237 | + ((unsigned int)src[2] ) | | |
238 | + ((unsigned int)src[1] << 24) ; | |
239 | + | |
240 | + dst[x] = pix; | |
241 | + } | |
242 | + } | |
243 | + } | |
244 | + else | |
245 | + { | |
246 | + /* convert horizontal BGR into ARGB32 */ | |
247 | + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) | |
248 | + { | |
249 | + int x; | |
250 | + unsigned char* src = srcLine; | |
251 | + unsigned int* dst = (unsigned int*)dstLine; | |
252 | + | |
253 | + for ( x = 0; x < width; x++, src += 3 ) | |
254 | + { | |
255 | + unsigned int pix; | |
256 | + | |
257 | + pix = ((unsigned int)src[2] << 16) | | |
258 | + ((unsigned int)src[1] << 8) | | |
259 | + ((unsigned int)src[0] ) | | |
260 | + ((unsigned int)src[1] << 24) ; | |
261 | + | |
262 | + dst[x] = pix; | |
263 | + } | |
264 | + } | |
265 | + } | |
266 | + break; | |
267 | + | |
268 | + default: /* FT_PIXEL_MODE_LCD_V */ | |
269 | + /* convert vertical RGB into ARGB32 */ | |
270 | + if ( !bgr ) | |
271 | + { | |
272 | + for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) | |
273 | + { | |
274 | + int x; | |
275 | + unsigned char* src = srcLine; | |
276 | + unsigned int* dst = (unsigned int*)dstLine; | |
277 | + | |
278 | + for ( x = 0; x < width; x++, src += 1 ) | |
279 | + { | |
280 | + unsigned int pix; | |
281 | +#if 1 | |
282 | + pix = ((unsigned int)src[0] << 16) | | |
283 | + ((unsigned int)src[src_pitch] << 8) | | |
284 | + ((unsigned int)src[src_pitch*2] ) | | |
285 | + 0xFF000000 ; | |
286 | +#else | |
287 | + pix = ((unsigned int)src[0] << 16) | | |
288 | + ((unsigned int)src[src_pitch] << 8) | | |
289 | + ((unsigned int)src[src_pitch*2] ) | | |
290 | + ((unsigned int)src[src_pitch] << 24) ; | |
291 | #endif | |
292 | - { 65538*9/13,65538*3/13,65538*1/13 }, | |
293 | - /* green */ | |
294 | - { 65538*1/6, 65538*4/6, 65538*1/6 }, | |
295 | - /* blue */ | |
296 | - { 65538*1/13,65538*3/13,65538*9/13 }, | |
297 | -}; | |
298 | + dst[x] = pix; | |
299 | + } | |
300 | + } | |
301 | + } | |
302 | + else | |
303 | + { | |
304 | + for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) | |
305 | + { | |
306 | + int x; | |
307 | + unsigned char* src = srcLine; | |
308 | + unsigned int* dst = (unsigned int*)dstLine; | |
309 | + | |
310 | + for ( x = 0; x < width; x++, src += 1 ) | |
311 | + { | |
312 | + unsigned int pix; | |
313 | + | |
314 | + pix = ((unsigned int)src[src_pitch*2] << 16) | | |
315 | + ((unsigned int)src[src_pitch] << 8) | | |
316 | + ((unsigned int)src[0] ) | | |
317 | + ((unsigned int)src[src_pitch] << 24) ; | |
318 | + | |
319 | + dst[x] = pix; | |
320 | + } | |
321 | + } | |
322 | + } | |
323 | + } | |
324 | +} | |
325 | + | |
326 | ||
327 | /* Fills in val->image with an image surface created from @bitmap | |
328 | */ | |
33282416 | 329 | @@ -731,7 +1010,7 @@ |
6e13550b | 330 | int width, height, stride; |
331 | unsigned char *data; | |
332 | int format = CAIRO_FORMAT_A8; | |
333 | - cairo_bool_t subpixel = FALSE; | |
334 | + cairo_image_surface_t *image; | |
335 | ||
336 | width = bitmap->width; | |
337 | height = bitmap->rows; | |
33282416 | 338 | @@ -772,7 +1051,6 @@ |
6e13550b | 339 | } |
340 | } | |
341 | } | |
342 | - | |
343 | #ifndef WORDS_BIGENDIAN | |
344 | { | |
345 | unsigned char *d = data; | |
33282416 | 346 | @@ -784,17 +1062,15 @@ |
6e13550b | 347 | } |
348 | } | |
349 | #endif | |
350 | + | |
351 | format = CAIRO_FORMAT_A1; | |
352 | break; | |
353 | ||
354 | case FT_PIXEL_MODE_LCD: | |
355 | case FT_PIXEL_MODE_LCD_V: | |
356 | case FT_PIXEL_MODE_GRAY: | |
357 | - switch (font_options->antialias) { | |
358 | - case CAIRO_ANTIALIAS_DEFAULT: | |
359 | - case CAIRO_ANTIALIAS_GRAY: | |
360 | - case CAIRO_ANTIALIAS_NONE: | |
361 | - default: | |
362 | + if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) | |
363 | + { | |
364 | stride = bitmap->pitch; | |
365 | if (own_buffer) { | |
366 | data = bitmap->buffer; | |
33282416 | 367 | @@ -807,105 +1083,16 @@ |
6e13550b | 368 | memcpy (data, bitmap->buffer, stride * height); |
369 | } | |
370 | format = CAIRO_FORMAT_A8; | |
371 | - break; | |
372 | - case CAIRO_ANTIALIAS_SUBPIXEL: { | |
373 | - int x, y; | |
374 | - unsigned char *in_line, *out_line, *in; | |
375 | - unsigned int *out; | |
376 | - unsigned int red, green, blue; | |
377 | - int rf, gf, bf; | |
378 | - int s; | |
379 | - int o, os; | |
380 | - unsigned char *data_rgba; | |
381 | - unsigned int width_rgba, stride_rgba; | |
382 | - int vmul = 1; | |
383 | - int hmul = 1; | |
96b7cd00 | 384 | - |
6e13550b | 385 | - switch (font_options->subpixel_order) { |
386 | - case CAIRO_SUBPIXEL_ORDER_DEFAULT: | |
387 | - case CAIRO_SUBPIXEL_ORDER_RGB: | |
388 | - case CAIRO_SUBPIXEL_ORDER_BGR: | |
389 | - default: | |
390 | - width /= 3; | |
391 | - hmul = 3; | |
392 | - break; | |
393 | - case CAIRO_SUBPIXEL_ORDER_VRGB: | |
394 | - case CAIRO_SUBPIXEL_ORDER_VBGR: | |
395 | - vmul = 3; | |
396 | - height /= 3; | |
397 | - break; | |
398 | - } | |
399 | - /* | |
400 | - * Filter the glyph to soften the color fringes | |
401 | - */ | |
402 | - width_rgba = width; | |
bc624305 | 403 | - stride = bitmap->pitch; |
6e13550b | 404 | - stride_rgba = (width_rgba * 4 + 3) & ~3; |
33282416 | 405 | - data_rgba = calloc (stride_rgba, height); |
96b7cd00 AM |
406 | - if (data_rgba == NULL) { |
407 | - if (own_buffer) | |
408 | - free (bitmap->buffer); | |
bc624305 | 409 | - _cairo_error (CAIRO_STATUS_NO_MEMORY); |
96b7cd00 AM |
410 | - return CAIRO_STATUS_NO_MEMORY; |
411 | - } | |
33282416 JB |
412 | + } else { |
413 | + // if we get there, the data from the source bitmap | |
414 | + // really comes from _fill_xrender_bitmap, and is | |
415 | + // made of 32-bit ARGB or ABGR values | |
416 | + assert(own_buffer != 0); | |
417 | + assert(bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); | |
418 | ||
6e13550b | 419 | - os = 1; |
420 | - switch (font_options->subpixel_order) { | |
421 | - case CAIRO_SUBPIXEL_ORDER_VRGB: | |
422 | - os = stride; | |
423 | - case CAIRO_SUBPIXEL_ORDER_DEFAULT: | |
424 | - case CAIRO_SUBPIXEL_ORDER_RGB: | |
425 | - default: | |
426 | - rf = 0; | |
427 | - gf = 1; | |
428 | - bf = 2; | |
429 | - break; | |
430 | - case CAIRO_SUBPIXEL_ORDER_VBGR: | |
431 | - os = stride; | |
432 | - case CAIRO_SUBPIXEL_ORDER_BGR: | |
433 | - bf = 0; | |
434 | - gf = 1; | |
435 | - rf = 2; | |
436 | - break; | |
437 | - } | |
438 | - in_line = bitmap->buffer; | |
439 | - out_line = data_rgba; | |
440 | - for (y = 0; y < height; y++) | |
441 | - { | |
442 | - in = in_line; | |
443 | - out = (unsigned int *) out_line; | |
444 | - in_line += stride * vmul; | |
445 | - out_line += stride_rgba; | |
446 | - for (x = 0; x < width * hmul; x += hmul) | |
447 | - { | |
448 | - red = green = blue = 0; | |
449 | - o = 0; | |
450 | - for (s = 0; s < 3; s++) | |
451 | - { | |
452 | - red += filters[rf][s]*in[x+o]; | |
453 | - green += filters[gf][s]*in[x+o]; | |
454 | - blue += filters[bf][s]*in[x+o]; | |
455 | - o += os; | |
456 | - } | |
457 | - red = red / 65536; | |
458 | - green = green / 65536; | |
459 | - blue = blue / 65536; | |
460 | - *out++ = (green << 24) | (red << 16) | (green << 8) | blue; | |
461 | - } | |
462 | - } | |
33282416 | 463 | - |
6e13550b | 464 | - /* Images here are stored in native format. The |
465 | - * backend must convert to its own format as needed | |
466 | - */ | |
467 | - | |
468 | - if (own_buffer) | |
469 | - free (bitmap->buffer); | |
470 | - data = data_rgba; | |
471 | - stride = stride_rgba; | |
bc624305 JB |
472 | + data = bitmap->buffer; |
473 | + stride = bitmap->pitch; | |
6e13550b | 474 | format = CAIRO_FORMAT_ARGB32; |
475 | - subpixel = TRUE; | |
476 | - break; | |
477 | - } | |
478 | } | |
479 | break; | |
6e13550b | 480 | case FT_PIXEL_MODE_GRAY2: |
33282416 | 481 | @@ -918,19 +1105,20 @@ |
6e13550b | 482 | return CAIRO_STATUS_NO_MEMORY; |
483 | } | |
484 | ||
485 | - *surface = (cairo_image_surface_t *) | |
486 | + /* XXX */ | |
487 | + *surface = image = (cairo_image_surface_t *) | |
488 | cairo_image_surface_create_for_data (data, | |
489 | format, | |
490 | width, height, stride); | |
491 | - if ((*surface)->base.status) { | |
492 | + if (image->base.status) { | |
493 | free (data); | |
494 | return CAIRO_STATUS_NO_MEMORY; | |
495 | } | |
496 | ||
497 | - if (subpixel) | |
498 | - pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); | |
6e13550b | 499 | + if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) |
500 | + pixman_image_set_component_alpha (image->pixman_image, TRUE); | |
501 | ||
33282416 | 502 | - _cairo_image_surface_assume_ownership_of_data ((*surface)); |
6e13550b | 503 | + _cairo_image_surface_assume_ownership_of_data (image); |
33282416 | 504 | |
6e13550b | 505 | return CAIRO_STATUS_SUCCESS; |
506 | } | |
33282416 | 507 | @@ -955,16 +1143,44 @@ |
6e13550b | 508 | cairo_font_options_t *font_options, |
509 | cairo_image_surface_t **surface) | |
510 | { | |
511 | + int rgba = FC_RGBA_UNKNOWN; | |
512 | FT_GlyphSlot glyphslot = face->glyph; | |
513 | FT_Outline *outline = &glyphslot->outline; | |
514 | FT_Bitmap bitmap; | |
515 | FT_BBox cbox; | |
516 | - FT_Matrix matrix; | |
517 | - int hmul = 1; | |
518 | - int vmul = 1; | |
519 | unsigned int width, height, stride; | |
520 | - cairo_bool_t subpixel = FALSE; | |
521 | + cairo_format_t format; | |
522 | cairo_status_t status; | |
523 | + FT_Error fterror; | |
524 | + FT_Library library = glyphslot->library; | |
525 | + FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL; | |
526 | + | |
527 | + switch (font_options->antialias) | |
528 | + { | |
529 | + case CAIRO_ANTIALIAS_NONE: | |
530 | + render_mode = FT_RENDER_MODE_MONO; | |
531 | + break; | |
532 | + | |
533 | + case CAIRO_ANTIALIAS_SUBPIXEL: | |
534 | + switch (font_options->subpixel_order) | |
535 | + { | |
536 | + case CAIRO_SUBPIXEL_ORDER_DEFAULT: | |
537 | + case CAIRO_SUBPIXEL_ORDER_RGB: | |
538 | + case CAIRO_SUBPIXEL_ORDER_BGR: | |
539 | + render_mode = FT_RENDER_MODE_LCD; | |
540 | + break; | |
541 | + | |
542 | + case CAIRO_SUBPIXEL_ORDER_VRGB: | |
543 | + case CAIRO_SUBPIXEL_ORDER_VBGR: | |
544 | + render_mode = FT_RENDER_MODE_LCD_V; | |
545 | + break; | |
546 | + } | |
547 | + break; | |
548 | + | |
549 | + case CAIRO_ANTIALIAS_DEFAULT: | |
550 | + case CAIRO_ANTIALIAS_GRAY: | |
551 | + render_mode = FT_RENDER_MODE_NORMAL; | |
552 | + } | |
553 | ||
554 | FT_Outline_Get_CBox (outline, &cbox); | |
555 | ||
33282416 | 556 | @@ -975,20 +1191,19 @@ |
6e13550b | 557 | |
558 | width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); | |
559 | height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); | |
560 | - stride = (width * hmul + 3) & ~3; | |
561 | + stride = (width + 3) & ~3; | |
562 | ||
563 | if (width * height == 0) { | |
564 | - cairo_format_t format; | |
565 | /* Looks like fb handles zero-sized images just fine */ | |
566 | - switch (font_options->antialias) { | |
567 | - case CAIRO_ANTIALIAS_NONE: | |
568 | + switch (render_mode) | |
569 | + { | |
570 | + case FT_RENDER_MODE_MONO: | |
571 | format = CAIRO_FORMAT_A1; | |
572 | break; | |
573 | - case CAIRO_ANTIALIAS_SUBPIXEL: | |
574 | - format= CAIRO_FORMAT_ARGB32; | |
575 | + case FT_RENDER_MODE_LCD: | |
576 | + case FT_RENDER_MODE_LCD_V: | |
577 | + format = CAIRO_FORMAT_ARGB32; | |
578 | break; | |
579 | - case CAIRO_ANTIALIAS_DEFAULT: | |
580 | - case CAIRO_ANTIALIAS_GRAY: | |
581 | default: | |
582 | format = CAIRO_FORMAT_A8; | |
33282416 JB |
583 | break; |
584 | @@ -1000,75 +1215,70 @@ | |
6e13550b | 585 | return CAIRO_STATUS_NO_MEMORY; |
6e13550b | 586 | } else { |
587 | ||
588 | - matrix.xx = matrix.yy = 0x10000L; | |
589 | - matrix.xy = matrix.yx = 0; | |
590 | + int bitmap_size; | |
591 | ||
592 | - switch (font_options->antialias) { | |
593 | - case CAIRO_ANTIALIAS_NONE: | |
594 | - bitmap.pixel_mode = FT_PIXEL_MODE_MONO; | |
595 | - bitmap.num_grays = 1; | |
596 | - stride = ((width + 31) & -32) >> 3; | |
597 | + switch (render_mode) | |
598 | + { | |
599 | + case FT_RENDER_MODE_LCD: | |
600 | + if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR ) { | |
601 | + rgba = FC_RGBA_BGR; | |
602 | + } else { | |
603 | + rgba = FC_RGBA_RGB; | |
604 | + } | |
605 | break; | |
606 | - case CAIRO_ANTIALIAS_DEFAULT: | |
607 | - case CAIRO_ANTIALIAS_GRAY: | |
608 | - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; | |
609 | - bitmap.num_grays = 256; | |
610 | - stride = (width + 3) & -4; | |
6e13550b | 611 | + case FT_RENDER_MODE_LCD_V: |
612 | + if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR ) { | |
613 | + rgba = FC_RGBA_VBGR; | |
614 | + } else { | |
615 | + rgba = FC_RGBA_VRGB; | |
616 | + } | |
617 | break; | |
618 | - case CAIRO_ANTIALIAS_SUBPIXEL: | |
619 | - switch (font_options->subpixel_order) { | |
620 | - case CAIRO_SUBPIXEL_ORDER_RGB: | |
621 | - case CAIRO_SUBPIXEL_ORDER_BGR: | |
622 | - case CAIRO_SUBPIXEL_ORDER_DEFAULT: | |
6e13550b | 623 | default: |
624 | - matrix.xx *= 3; | |
625 | - hmul = 3; | |
626 | - subpixel = TRUE; | |
33282416 | 627 | break; |
6e13550b | 628 | - case CAIRO_SUBPIXEL_ORDER_VRGB: |
629 | - case CAIRO_SUBPIXEL_ORDER_VBGR: | |
630 | - matrix.yy *= 3; | |
631 | - vmul = 3; | |
632 | - subpixel = TRUE; | |
633 | - break; | |
33282416 | 634 | - } |
6e13550b | 635 | - FT_Outline_Transform (outline, &matrix); |
33282416 | 636 | - |
6e13550b | 637 | - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; |
638 | - bitmap.num_grays = 256; | |
639 | - stride = (width * hmul + 3) & -4; | |
33282416 | 640 | } |
6e13550b | 641 | |
642 | - bitmap.pitch = stride; | |
643 | - bitmap.width = width * hmul; | |
644 | - bitmap.rows = height * vmul; | |
33282416 JB |
645 | - bitmap.buffer = calloc (stride, bitmap.rows); |
646 | + FT_Library_SetLcdFilter( library, FT_LCD_FILTER_DEFAULT ); | |
647 | + | |
6e13550b | 648 | + fterror = FT_Render_Glyph( face->glyph, render_mode ); |
649 | ||
650 | - if (bitmap.buffer == NULL) { | |
651 | + FT_Library_SetLcdFilter( library, FT_LCD_FILTER_NONE ); | |
652 | + | |
bc624305 JB |
653 | + if (fterror != 0) { |
654 | _cairo_error (CAIRO_STATUS_NO_MEMORY); | |
6e13550b | 655 | return CAIRO_STATUS_NO_MEMORY; |
bc624305 | 656 | } |
6e13550b | 657 | |
658 | - FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); | |
659 | + bitmap_size = _compute_xrender_bitmap_size( &bitmap, | |
660 | + face->glyph, | |
661 | + render_mode ); | |
bc624305 JB |
662 | + if ( bitmap_size < 0 ) { |
663 | + _cairo_error (CAIRO_STATUS_NO_MEMORY); | |
6e13550b | 664 | + return CAIRO_STATUS_NO_MEMORY; |
bc624305 | 665 | + } |
6e13550b | 666 | |
667 | - if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { | |
6e13550b | 668 | + bitmap.buffer = calloc(1, bitmap_size); |
669 | + if (bitmap.buffer == NULL) { | |
33282416 | 670 | free (bitmap.buffer); |
bc624305 | 671 | _cairo_error (CAIRO_STATUS_NO_MEMORY); |
6e13550b | 672 | return CAIRO_STATUS_NO_MEMORY; |
673 | } | |
674 | ||
675 | + _fill_xrender_bitmap( &bitmap, face->glyph, render_mode, | |
676 | + (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR) ); | |
677 | + | |
678 | + // NOTE: _get_bitmap_surface will free bitmap.buffer if there is an error | |
679 | status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); | |
680 | if (status) | |
681 | return status; | |
682 | - } | |
683 | ||
684 | /* | |
685 | * Note: the font's coordinate system is upside down from ours, so the | |
686 | * Y coordinate of the control box needs to be negated. | |
687 | */ | |
688 | cairo_surface_set_device_offset (&(*surface)->base, | |
689 | - floor ((double) cbox.xMin / 64.0), | |
690 | - floor (-(double) cbox.yMax / 64.0)); | |
691 | + (double) glyphslot->bitmap_left, | |
692 | + (double)-glyphslot->bitmap_top); | |
693 | + } | |
694 | ||
695 | return CAIRO_STATUS_SUCCESS; | |
696 | } | |
33282416 | 697 | @@ -1442,11 +1652,11 @@ |
6e13550b | 698 | case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
699 | case CAIRO_SUBPIXEL_ORDER_RGB: | |
700 | case CAIRO_SUBPIXEL_ORDER_BGR: | |
701 | - load_target |= FT_LOAD_TARGET_LCD; | |
702 | + load_target = FT_LOAD_TARGET_LCD; | |
703 | break; | |
704 | case CAIRO_SUBPIXEL_ORDER_VRGB: | |
705 | case CAIRO_SUBPIXEL_ORDER_VBGR: | |
706 | - load_target |= FT_LOAD_TARGET_LCD_V; | |
707 | + load_target = FT_LOAD_TARGET_LCD_V; | |
708 | break; | |
709 | } | |
710 | } |