diff options
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r--[-rwxr-xr-x] | src/cairo-ft-font.c | 232 |
1 files changed, 138 insertions, 94 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 43df78e0b..868ccc2c8 100755..100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -45,6 +45,7 @@ #include "cairo-image-surface-private.h" #include "cairo-ft-private.h" #include "cairo-pattern-private.h" +#include "cairo-pixman-private.h" #include <float.h> @@ -54,11 +55,11 @@ #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_IMAGE_H +#include FT_BITMAP_H #include FT_TRUETYPE_TABLES_H #include FT_XFREE86_H #if HAVE_FT_GLYPHSLOT_EMBOLDEN #include FT_SYNTHESIS_H -#define USE_FT_OUTLINE_EMBOLDEN 1 #endif #if HAVE_FT_LIBRARY_SETLCDFILTER @@ -587,23 +588,20 @@ _cairo_ft_unscaled_font_create_from_face (FT_Face face, return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out); } -static void +static cairo_bool_t _cairo_ft_unscaled_font_destroy (void *abstract_font) { cairo_ft_unscaled_font_t *unscaled = abstract_font; cairo_ft_unscaled_font_map_t *font_map; - if (unscaled == NULL) - return; - font_map = _cairo_ft_unscaled_font_map_lock (); /* All created objects must have been mapped in the font map. */ assert (font_map != NULL); - if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) { + if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)) { /* somebody recreated the font whilst we waited for the lock */ _cairo_ft_unscaled_font_map_unlock (); - return; + return FALSE; } _cairo_hash_table_remove (font_map->hash_table, @@ -625,6 +623,7 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font) _cairo_ft_unscaled_font_map_unlock (); _cairo_ft_unscaled_font_fini (unscaled); + return TRUE; } static cairo_bool_t @@ -740,19 +739,26 @@ _compute_transform (cairo_ft_font_transform_t *sf, if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) { double min_distance = DBL_MAX; + cairo_bool_t magnify = TRUE; int i; - int best_i = 0; double best_x_size = 0; double best_y_size = 0; for (i = 0; i < unscaled->face->num_fixed_sizes; i++) { - double x_size = unscaled->face->available_sizes[i].y_ppem / 64.; + double x_size = unscaled->face->available_sizes[i].x_ppem / 64.; double y_size = unscaled->face->available_sizes[i].y_ppem / 64.; - double distance = fabs (y_size - y_scale); + double distance = y_size - y_scale; + + /* + * distance is positive if current strike is larger than desired + * size, and negative if smaller. + * + * We like to prefer down-scaling to upscaling. + */ - if (distance <= min_distance) { - min_distance = distance; - best_i = i; + if ((magnify && distance >= 0) || fabs (distance) <= min_distance) { + magnify = distance < 0; + min_distance = fabs (distance); best_x_size = x_size; best_y_size = y_size; } @@ -1114,15 +1120,17 @@ _fill_xrender_bitmap(FT_Bitmap *target, */ static cairo_status_t _get_bitmap_surface (FT_Bitmap *bitmap, + FT_Library library, cairo_bool_t own_buffer, cairo_font_options_t *font_options, cairo_image_surface_t **surface) { - int width, height, stride; + unsigned int width, height; unsigned char *data; int format = CAIRO_FORMAT_A8; + int stride; cairo_image_surface_t *image; - cairo_bool_t component_alpha = TRUE; + cairo_bool_t component_alpha = TRUE; width = bitmap->width; height = bitmap->rows; @@ -1179,8 +1187,18 @@ _get_bitmap_surface (FT_Bitmap *bitmap, case FT_PIXEL_MODE_LCD: case FT_PIXEL_MODE_LCD_V: case FT_PIXEL_MODE_GRAY: - if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) { + if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL || + bitmap->pixel_mode == FT_PIXEL_MODE_GRAY) + { stride = bitmap->pitch; + + /* We don't support stride not multiple of 4. */ + if (stride & 3) + { + assert (!own_buffer); + goto convert; + } + if (own_buffer) { data = bitmap->buffer; } else { @@ -1193,49 +1211,91 @@ _get_bitmap_surface (FT_Bitmap *bitmap, format = CAIRO_FORMAT_A8; } else { - /* color glyph is rendered as bitmap, does not come from - * _fill_xrender_bitmap */ - if (! own_buffer) { - stride = bitmap->pitch; - data = _cairo_malloc_ab (height, stride); - if (!data) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (data, bitmap->buffer, stride * height); - format = CAIRO_FORMAT_A8; - } else { - /* if we get there, the data from the source bitmap - * really comes from _fill_xrender_bitmap, and is - * made of 32-bit ARGB or ABGR values */ - assert (own_buffer != 0); - assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); - - data = bitmap->buffer; - stride = bitmap->pitch; - format = CAIRO_FORMAT_ARGB32; - } - } - break; - // color font - /* - case FT_PIXEL_MODE_BGRA: + /* color glyph is rendered as bitmap, does not come from + * _fill_xrender_bitmap */ + if (! own_buffer) { stride = bitmap->pitch; - if (own_buffer) { - data = bitmap->buffer; - } else { - data = _cairo_malloc_ab (height, stride); - if (!data) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (data, bitmap->buffer, stride * height); - } + data = _cairo_malloc_ab (height, stride); + if (!data) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + memcpy (data, bitmap->buffer, stride * height); + format = CAIRO_FORMAT_A8; + } else { + /* if we get there, the data from the source bitmap + * really comes from _fill_xrender_bitmap, and is + * made of 32-bit ARGB or ABGR values */ + assert (own_buffer != 0); + assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); + data = bitmap->buffer; + stride = bitmap->pitch; format = CAIRO_FORMAT_ARGB32; - component_alpha = FALSE; + } + } break; - */ + // color font + #if 0 // TODO(suyambu.rm) Build error for Tizen 3.0 + case FT_PIXEL_MODE_BGRA: + stride = bitmap->pitch; + + if (own_buffer) { + data = bitmap->buffer; + } else { + data = _cairo_malloc_ab (height, stride); + if (!data) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + memcpy (data, bitmap->buffer, stride * height); + } + + format = CAIRO_FORMAT_ARGB32; + component_alpha = FALSE; + break; + #endif case FT_PIXEL_MODE_GRAY2: case FT_PIXEL_MODE_GRAY4: + convert: + if (!own_buffer && library) + { + /* This is pretty much the only case that we can get in here. */ + /* Convert to 8bit grayscale. */ + + FT_Bitmap tmp; + FT_Int align; + + format = CAIRO_FORMAT_A8; + + align = cairo_format_stride_for_width (format, bitmap->width); + + FT_Bitmap_New( &tmp ); + + if (FT_Bitmap_Convert( library, bitmap, &tmp, align )) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + FT_Bitmap_Done( library, bitmap ); + *bitmap = tmp; + + stride = bitmap->pitch; + data = _cairo_malloc_ab (height, stride); + if (!data) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + if (bitmap->num_grays != 256) + { + unsigned int x, y; + unsigned int mul = 255 / (bitmap->num_grays - 1); + FT_Byte *p = bitmap->buffer; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + p[x] *= mul; + p += bitmap->pitch; + } + } + + memcpy (data, bitmap->buffer, stride * height); + break; + } /* These could be triggered by very rare types of TrueType fonts */ default: if (own_buffer) @@ -1429,7 +1489,7 @@ _render_glyph_outline (FT_Face face, /* Note: * _get_bitmap_surface will free bitmap.buffer if there is an error */ - status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); + status = _get_bitmap_surface (&bitmap, NULL, TRUE, font_options, surface); if (unlikely (status)) return status; @@ -1470,6 +1530,7 @@ _render_glyph_bitmap (FT_Face face, return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _get_bitmap_surface (&glyphslot->bitmap, + glyphslot->library, FALSE, font_options, surface); if (unlikely (status)) @@ -1511,7 +1572,7 @@ _transform_glyph_bitmap (cairo_matrix_t * shape, * the "shape" portion of the font transform */ original_to_transformed = *shape; - + cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y); orig_width = (*surface)->width; orig_height = (*surface)->height; @@ -2193,10 +2254,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, vertical_layout = TRUE; } - #ifdef FT_LOAD_COLOR - /*Color-glyph support */ - load_flags |= FT_LOAD_COLOR; - #endif +#ifdef FT_LOAD_COLOR + /* Color-glyph support: + * + * This flags needs plumbing through fontconfig (does it?), and + * maybe we should cache color and grayscale bitmaps separately + * such that users of the font (ie. the surface) can choose which + * version to use based on target content type. + * + * Moreover, none of our backends and compositors currently support + * color glyphs. As such, this is currently disabled. + */ + /* load_flags |= FT_LOAD_COLOR; */ + + /* Color-glyph support */ + if (scaled_font->ft_options.base.color == CAIRO_FONT_COLOR_DEFAULT) + load_flags |= FT_LOAD_COLOR; +#endif error = FT_Load_Glyph (face, _cairo_scaled_glyph_index(scaled_glyph), @@ -2215,22 +2289,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, */ #if HAVE_FT_GLYPHSLOT_EMBOLDEN if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD) -#if USE_FT_OUTLINE_EMBOLDEN - { - /*UX team request us to use 64 instead 34*/ - FT_Pos xstr; - if(face && face->size) - xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64; - else - goto FAIL; - if(face->glyph) - FT_Outline_Embolden(&face->glyph->outline, xstr); - else - goto FAIL; - } -#else FT_GlyphSlot_Embolden (glyph); -#endif // USE_FT_OUTLINE_EMBOLDEN #endif #if HAVE_FT_GLYPHSLOT_OBLIQUE @@ -2384,22 +2443,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, } #if HAVE_FT_GLYPHSLOT_EMBOLDEN if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD) -#if USE_FT_OUTLINE_EMBOLDEN - { - /*UX team request us to use 64 instead 34*/ - FT_Pos xstr; - if(face && face->size) - xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64; - else - goto FAIL; - if(face->glyph) - FT_Outline_Embolden(&face->glyph->outline, xstr); - else - goto FAIL; - } -#else - FT_GlyphSlot_Embolden (glyph); -#endif // USE_FT_OUTLINE_EMBOLDEN + FT_GlyphSlot_Embolden (glyph); #endif #if HAVE_FT_GLYPHSLOT_OBLIQUE if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE) @@ -2752,7 +2796,7 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, } #endif -static void +static cairo_bool_t _cairo_ft_font_face_destroy (void *abstract_face) { cairo_ft_font_face_t *font_face = abstract_face; @@ -2778,12 +2822,10 @@ _cairo_ft_font_face_destroy (void *abstract_face) font_face->unscaled->faces == font_face && CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1) { - cairo_font_face_reference (&font_face->base); - _cairo_unscaled_font_destroy (&font_face->unscaled->base); font_face->unscaled = NULL; - return; + return FALSE; } if (font_face->unscaled) { @@ -2815,6 +2857,8 @@ _cairo_ft_font_face_destroy (void *abstract_face) cairo_font_face_destroy (font_face->resolved_font_face); } #endif + + return TRUE; } static cairo_font_face_t * |