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