diff options
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r-- | src/cairo-ft-font.c | 526 |
1 files changed, 329 insertions, 197 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index afe80dff..36a0c674 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -76,31 +76,31 @@ * factors so that hinting works right */ -typedef struct { +typedef struct _cairo_ft_font_transform { double x_scale, y_scale; double shape[2][2]; -} ft_font_transform_t; +} cairo_ft_font_transform_t; /* * We create an object that corresponds to a single font on the disk; * (identified by a filename/id pair) these are shared between all - * fonts using that file. For cairo_ft_scaled_font_create_for_ft_face(), we + * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we * just create a one-off version with a permanent face value. */ -typedef struct _ft_font_face ft_font_face_t; +typedef struct _cairo_ft_font_face cairo_ft_font_face_t; -typedef struct { +struct _cairo_ft_unscaled_font { cairo_unscaled_font_t base; - cairo_bool_t from_face; /* from cairo_ft_scaled_font_create_for_ft_face()? */ + cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */ FT_Face face; /* provided or cached face */ /* only set if from_face is false */ char *filename; int id; - /* We temporarily scale the unscaled font as neede */ + /* We temporarily scale the unscaled font as needed */ cairo_bool_t have_scale; cairo_matrix_t current_scale; double x_scale; /* Extracted X scale factor */ @@ -109,38 +109,91 @@ typedef struct { int lock; /* count of how many times this font has been locked */ - ft_font_face_t *faces; /* Linked list of faces for this font */ -} ft_unscaled_font_t; + cairo_ft_font_face_t *faces; /* Linked list of faces for this font */ +}; -struct _ft_font_face { +struct _cairo_ft_font_face { cairo_font_face_t base; - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; int load_flags; - ft_font_face_t *next_face; + cairo_ft_font_face_t *next; }; const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend; -static ft_unscaled_font_t * -_ft_unscaled_font_create_from_face (FT_Face face) +/** + * _cairo_ft_unscaled_font_init: + * + * Initialize a cairo_ft_unscaled_font_t. + * + * There are two basic flavors of cairo_ft_unscaled_font_t, one + * created from an FT_Face and the other created from a filename/id + * pair. These two flavors are identified as from_face and !from_face. + * + * To initialize a from_face font, pass filename==NULL, id=0 and the + * desired face. + * + * To initialize a !from_face font, pass the filename/id as desired + * and face==NULL. + * + * Note that the code handles these two flavors in very distinct + * ways. For example there is a hash_table mapping + * filename/id->cairo_unscaled_font_t in the !from_face case, but no + * parallel in the from_face case, (where the calling code would have + * to do its own mapping to ensure similar sharing). + **/ +static cairo_status_t +_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, + const char *filename, + int id, + FT_Face face) { - ft_unscaled_font_t *unscaled = malloc (sizeof(ft_unscaled_font_t)); - if (!unscaled) - return NULL; - - unscaled->from_face = 1; - unscaled->face = face; + char *filename_copy = NULL; + + if (filename) { + filename_copy = strdup (filename); + if (filename_copy == NULL) + return CAIRO_STATUS_NO_MEMORY; + } + + unscaled->filename = filename_copy; + unscaled->id = id; + + if (face) { + unscaled->from_face = 1; + unscaled->face = face; + } else { + unscaled->from_face = 0; + unscaled->face = NULL; + } - unscaled->filename = NULL; - unscaled->id = 0; - unscaled->have_scale = 0; unscaled->lock = 0; - + unscaled->faces = NULL; _cairo_unscaled_font_init (&unscaled->base, &cairo_ft_unscaled_font_backend); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_ft_unscaled_font_t * +_cairo_ft_unscaled_font_create_from_face (FT_Face face) +{ + cairo_status_t status; + cairo_ft_unscaled_font_t *unscaled; + + unscaled = malloc (sizeof (cairo_ft_unscaled_font_t)); + if (unscaled == NULL) + return NULL; + + status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face); + if (status) { + free (unscaled); + return NULL; + } + return unscaled; } @@ -150,36 +203,23 @@ _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font) return unscaled_font->backend == &cairo_ft_unscaled_font_backend; } -static ft_unscaled_font_t * -_ft_unscaled_font_create_from_filename (const char *filename, - int id) +static cairo_ft_unscaled_font_t * +_cairo_ft_unscaled_font_create_from_filename (const char *filename, + int id) { - ft_unscaled_font_t *unscaled; - char *new_filename; + cairo_status_t status; + cairo_ft_unscaled_font_t *unscaled; - new_filename = strdup (filename); - if (!new_filename) + unscaled = malloc (sizeof (cairo_ft_unscaled_font_t)); + if (unscaled == NULL) return NULL; - unscaled = malloc (sizeof (ft_unscaled_font_t)); - if (!unscaled) { - free (new_filename); + status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL); + if (status) { + free (unscaled); return NULL; } - - unscaled->from_face = 0; - unscaled->face = NULL; - - unscaled->filename = new_filename; - unscaled->id = id; - - unscaled->have_scale = 0; - unscaled->lock = 0; - - unscaled->faces = NULL; - _cairo_unscaled_font_init (&unscaled->base, - &cairo_ft_unscaled_font_backend); return unscaled; } @@ -199,7 +239,7 @@ typedef struct { typedef struct { cairo_ft_cache_key_t key; - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; } cairo_ft_cache_entry_t; typedef struct { @@ -209,7 +249,7 @@ typedef struct { } ft_cache_t; static unsigned long -_ft_font_cache_hash (void *cache, void *key) +_cairo_ft_font_cache_hash (void *cache, void *key) { cairo_ft_cache_key_t *in = (cairo_ft_cache_key_t *) key; unsigned long hash; @@ -222,9 +262,9 @@ _ft_font_cache_hash (void *cache, void *key) } static int -_ft_font_cache_keys_equal (void *cache, - void *k1, - void *k2) +_cairo_ft_font_cache_keys_equal (void *cache, + void *k1, + void *k2) { cairo_ft_cache_key_t *a; cairo_ft_cache_key_t *b; @@ -236,9 +276,9 @@ _ft_font_cache_keys_equal (void *cache, } static cairo_status_t -_ft_font_cache_create_entry (void *cache, - void *key, - void **return_entry) +_cairo_ft_font_cache_create_entry (void *cache, + void *key, + void **return_entry) { cairo_ft_cache_key_t *k = key; cairo_ft_cache_entry_t *entry; @@ -247,8 +287,8 @@ _ft_font_cache_create_entry (void *cache, if (entry == NULL) return CAIRO_STATUS_NO_MEMORY; - entry->unscaled = _ft_unscaled_font_create_from_filename (k->filename, - k->id); + entry->unscaled = _cairo_ft_unscaled_font_create_from_filename (k->filename, + k->id); if (!entry->unscaled) { free (entry); return CAIRO_STATUS_NO_MEMORY; @@ -268,8 +308,8 @@ _ft_font_cache_create_entry (void *cache, * in the code that removes the entry from the cache */ static void -_ft_font_cache_destroy_entry (void *cache, - void *entry) +_cairo_ft_font_cache_destroy_entry (void *cache, + void *entry) { cairo_ft_cache_entry_t *e = (cairo_ft_cache_entry_t *) entry; @@ -277,7 +317,7 @@ _ft_font_cache_destroy_entry (void *cache, } static void -_ft_font_cache_destroy_cache (void *cache) +_cairo_ft_font_cache_destroy_cache (void *cache) { ft_cache_t *fc = (ft_cache_t *) cache; @@ -286,11 +326,11 @@ _ft_font_cache_destroy_cache (void *cache) } static const cairo_cache_backend_t _ft_font_cache_backend = { - _ft_font_cache_hash, - _ft_font_cache_keys_equal, - _ft_font_cache_create_entry, - _ft_font_cache_destroy_entry, - _ft_font_cache_destroy_cache + _cairo_ft_font_cache_hash, + _cairo_ft_font_cache_keys_equal, + _cairo_ft_font_cache_create_entry, + _cairo_ft_font_cache_destroy_entry, + _cairo_ft_font_cache_destroy_cache }; static ft_cache_t *_global_ft_cache = NULL; @@ -339,8 +379,8 @@ _get_global_ft_cache (void) /* Finds or creates a ft_unscaled_font for the filename/id from pattern. * Returns a new reference to the unscaled font. */ -static ft_unscaled_font_t * -_ft_unscaled_font_get_for_pattern (FcPattern *pattern) +static cairo_ft_unscaled_font_t * +_cairo_ft_unscaled_font_get_for_pattern (FcPattern *pattern) { cairo_ft_cache_entry_t *entry; cairo_ft_cache_key_t key; @@ -384,9 +424,12 @@ _has_unlocked_face (void *entry) /* Ensures that an unscaled font has a face object. If we exceed * MAX_OPEN_FACES, try to close some. + * + * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't + * set the scale on the face, but just returns it at the last scale. */ -static FT_Face -_ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled) +FT_Face +_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) { ft_cache_t *ftcache; FT_Face face = NULL; @@ -433,8 +476,8 @@ _ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled) /* Unlock unscaled font locked with _ft_unscaled_font_lock_face */ -static void -_ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled) +void +_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled) { assert (unscaled->lock > 0); @@ -442,7 +485,7 @@ _ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled) } static void -_compute_transform (ft_font_transform_t *sf, +_compute_transform (cairo_ft_font_transform_t *sf, cairo_matrix_t *scale) { cairo_matrix_t normalized = *scale; @@ -476,10 +519,10 @@ _compute_transform (ft_font_transform_t *sf, * scaling to the same size, since changing a FT_Face is expensive. */ static void -_ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled, - cairo_matrix_t *scale) +_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, + cairo_matrix_t *scale) { - ft_font_transform_t sf; + cairo_ft_font_transform_t sf; FT_Matrix mat; FT_UInt pixel_width, pixel_height; FT_Error error; @@ -528,7 +571,11 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled, pixel_width = pixel_height = 0; for (i = 0; i < unscaled->face->num_fixed_sizes; i++) { +#if HAVE_FT_BITMAP_SIZE_Y_PPEM double size = unscaled->face->available_sizes[i].y_ppem / 64.; +#else + double size = unscaled->face->available_sizes[i].height; +#endif double distance = fabs (size - sf.y_scale); if (distance <= min_distance) { @@ -536,11 +583,13 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled, best_i = i; } } +#if HAVE_FT_BITMAP_SIZE_Y_PPEM error = FT_Set_Char_Size (unscaled->face, unscaled->face->available_sizes[best_i].x_ppem, unscaled->face->available_sizes[best_i].y_ppem, 0, 0); - if (error ) + if (error) +#endif error = FT_Set_Pixel_Sizes (unscaled->face, unscaled->face->available_sizes[best_i].width, unscaled->face->available_sizes[best_i].height); @@ -552,7 +601,7 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled, static void _cairo_ft_unscaled_font_destroy (void *abstract_font) { - ft_unscaled_font_t *unscaled = abstract_font; + cairo_ft_unscaled_font_t *unscaled = abstract_font; if (unscaled == NULL) return; @@ -990,7 +1039,7 @@ _render_glyph_bitmap (FT_Face face, static cairo_status_t _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) { - ft_font_transform_t sf; + cairo_ft_font_transform_t sf; cairo_matrix_t original_to_transformed; cairo_matrix_t transformed_to_original; cairo_image_surface_t *old_image; @@ -1110,21 +1159,21 @@ static cairo_status_t _cairo_ft_unscaled_font_create_glyph (void *abstract_font, cairo_image_glyph_cache_entry_t *val) { - ft_unscaled_font_t *unscaled = abstract_font; + cairo_ft_unscaled_font_t *unscaled = abstract_font; FT_GlyphSlot glyphslot; FT_Face face; FT_Glyph_Metrics *metrics; cairo_status_t status = CAIRO_STATUS_SUCCESS; double x_factor, y_factor; - face = _ft_unscaled_font_lock_face (unscaled); + face = _cairo_ft_unscaled_font_lock_face (unscaled); if (!face) return CAIRO_STATUS_NO_MEMORY; glyphslot = face->glyph; metrics = &glyphslot->metrics; - _ft_unscaled_font_set_scale (unscaled, &val->key.scale); + _cairo_ft_unscaled_font_set_scale (unscaled, &val->key.scale); if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) { status = CAIRO_STATUS_NO_MEMORY; @@ -1203,7 +1252,7 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_ val->image = NULL; } - _ft_unscaled_font_unlock_face (unscaled); + _cairo_ft_unscaled_font_unlock_face (unscaled); return status; } @@ -1215,11 +1264,10 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { /* cairo_ft_scaled_font_t */ -typedef struct { +typedef struct _cairo_ft_scaled_font { cairo_scaled_font_t base; int load_flags; - cairo_font_options_t options; - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; } cairo_ft_scaled_font_t; const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend; @@ -1370,31 +1418,31 @@ _get_options_load_flags (const cairo_font_options_t *options) } static cairo_scaled_font_t * -_ft_scaled_font_create (ft_unscaled_font_t *unscaled, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - int load_flags) +_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + int load_flags) { - cairo_ft_scaled_font_t *f = NULL; + cairo_ft_scaled_font_t *scaled_font = NULL; - f = malloc (sizeof(cairo_ft_scaled_font_t)); - if (f == NULL) + scaled_font = malloc (sizeof(cairo_ft_scaled_font_t)); + if (scaled_font == NULL) return NULL; - f->unscaled = unscaled; + scaled_font->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); - f->options = *options; - if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) load_flags |= PRIVATE_FLAG_HINT_METRICS; - f->load_flags = load_flags; + scaled_font->load_flags = load_flags; - _cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend); + _cairo_scaled_font_init (&scaled_font->base, + font_matrix, ctm, options, + &cairo_ft_scaled_font_backend); - return (cairo_scaled_font_t *)f; + return (cairo_scaled_font_t*) scaled_font; } cairo_bool_t @@ -1404,28 +1452,28 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font) } static cairo_status_t -_cairo_ft_scaled_font_create (const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font) +_cairo_ft_scaled_font_create_toy (const cairo_toy_font_face_t *toy_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **font) { FcPattern *pattern, *resolved; - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; cairo_scaled_font_t *new_font; FcResult result; int fcslant; int fcweight; cairo_matrix_t scale; - ft_font_transform_t sf; + cairo_ft_font_transform_t sf; + int load_flags; + unsigned char *family = (unsigned char*) toy_face->family; pattern = FcPatternCreate (); if (!pattern) return CAIRO_STATUS_NO_MEMORY; - switch (weight) + switch (toy_face->weight) { case CAIRO_FONT_WEIGHT_BOLD: fcweight = FC_WEIGHT_BOLD; @@ -1436,7 +1484,7 @@ _cairo_ft_scaled_font_create (const char *family, break; } - switch (slant) + switch (toy_face->slant) { case CAIRO_FONT_SLANT_ITALIC: fcslant = FC_SLANT_ITALIC; @@ -1450,7 +1498,7 @@ _cairo_ft_scaled_font_create (const char *family, break; } - if (!FcPatternAddString (pattern, FC_FAMILY, (unsigned char *) family)) + if (!FcPatternAddString (pattern, FC_FAMILY, family)) goto FREE_PATTERN; if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) goto FREE_PATTERN; @@ -1470,13 +1518,15 @@ _cairo_ft_scaled_font_create (const char *family, if (!resolved) goto FREE_PATTERN; - unscaled = _ft_unscaled_font_get_for_pattern (resolved); + unscaled = _cairo_ft_unscaled_font_get_for_pattern (resolved); if (!unscaled) goto FREE_RESOLVED; - - new_font = _ft_scaled_font_create (unscaled, - font_matrix, ctm, - options, _get_pattern_load_flags (pattern)); + + load_flags = _get_pattern_load_flags (pattern); + new_font = _cairo_ft_scaled_font_create (unscaled, + font_matrix, ctm, + options, load_flags); + _cairo_unscaled_font_destroy (&unscaled->base); FcPatternDestroy (resolved); @@ -1499,7 +1549,7 @@ _cairo_ft_scaled_font_create (const char *family, } static void -_cairo_ft_scaled_font_destroy (void *abstract_font) +_cairo_ft_scaled_font_fini (void *abstract_font) { cairo_ft_scaled_font_t *scaled_font = abstract_font; @@ -1599,19 +1649,20 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font, FT_Face face; FT_Size_Metrics *metrics; - face = _ft_unscaled_font_lock_face (scaled_font->unscaled); + face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled); if (!face) return CAIRO_STATUS_NO_MEMORY; metrics = &face->size->metrics; - _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale); + _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, + &scaled_font->base.scale); /* * Get to unscaled metrics so that the upper level can get back to * user space */ - if (scaled_font->options.hint_metrics != CAIRO_HINT_METRICS_OFF) { + if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { double x_factor, y_factor; if (scaled_font->unscaled->x_scale == 0) @@ -1640,7 +1691,7 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font, /* FIXME: this doesn't do vertical layout atm. */ extents->max_y_advance = 0.0; - _ft_unscaled_font_unlock_face (scaled_font->unscaled); + _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); return CAIRO_STATUS_SUCCESS; } @@ -1697,7 +1748,7 @@ _cairo_ft_scaled_font_glyph_extents (void *abstract_font, /* XXX: Need to add code here to check the font's FcPattern for FC_VERTICAL_LAYOUT and if set get vertBearingX/Y instead. This will require that - cairo_ft_scaled_font_create_for_ft_face accept an + cairo_ft_font_face_create_for_ft_face accept an FcPattern. */ glyph_min.x = glyphs[i].x + img->extents.x_bearing; glyph_min.y = glyphs[i].y + img->extents.y_bearing; @@ -1793,6 +1844,26 @@ _cairo_ft_scaled_font_glyph_bbox (void *abstract_font, return CAIRO_STATUS_SUCCESS; } +static cairo_format_t +_select_text_mask_format (cairo_bool_t have_a1_glyphs, + cairo_bool_t have_a8_glyphs, + cairo_bool_t have_argb32_glyphs) +{ + if (have_a8_glyphs) + return CAIRO_FORMAT_A8; + + if (have_a1_glyphs && have_argb32_glyphs) + return CAIRO_FORMAT_A8; + + if (have_a1_glyphs) + return CAIRO_FORMAT_A1; + + if (have_argb32_glyphs) + return CAIRO_FORMAT_ARGB32; + + /* when there are no glyphs to draw, just pick something */ + return CAIRO_FORMAT_A8; +} static cairo_status_t _cairo_ft_scaled_font_show_glyphs (void *abstract_font, @@ -1808,12 +1879,16 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font, const cairo_glyph_t *glyphs, int num_glyphs) { - cairo_image_glyph_cache_entry_t *img; + cairo_image_glyph_cache_entry_t **entries; cairo_cache_t *cache; cairo_glyph_cache_key_t key; cairo_ft_scaled_font_t *scaled_font = abstract_font; cairo_surface_pattern_t glyph_pattern; - cairo_status_t status; + cairo_surface_t *mask; + cairo_surface_pattern_t mask_pattern; + cairo_format_t mask_format = CAIRO_FORMAT_A1; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_bool_t have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs; int x, y; int i; @@ -1833,44 +1908,98 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font, key.scale = scaled_font->base.scale; key.flags = scaled_font->load_flags; + entries = malloc (num_glyphs * sizeof (cairo_image_glyph_cache_entry_t)); + if (!entries) + goto CLEANUP_CACHE; + + have_a1_glyphs = FALSE; + have_a8_glyphs = FALSE; + have_argb32_glyphs = FALSE; + for (i = 0; i < num_glyphs; i++) { - img = NULL; + entries[i] = NULL; key.index = glyphs[i].index; - if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL) - != CAIRO_STATUS_SUCCESS - || img == NULL - || img->image == NULL) + if (_cairo_cache_lookup (cache, &key, (void **) &entries[i], NULL) != CAIRO_STATUS_SUCCESS) + continue; + + switch (entries[i]->image->format) { + case CAIRO_FORMAT_A1: + have_a1_glyphs = TRUE; + break; + case CAIRO_FORMAT_A8: + have_a8_glyphs = TRUE; + break; + case CAIRO_FORMAT_ARGB32: + have_argb32_glyphs = TRUE; + break; + default: + break; + } + } + + mask_format = _select_text_mask_format (have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs); + + mask = cairo_image_surface_create (mask_format, width, height); + if (!mask) + goto CLEANUP_ENTRIES; + + status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_SOURCE, + CAIRO_COLOR_TRANSPARENT, + 0, 0, width, height); + if (status) + goto CLEANUP_MASK; + + for (i = 0; i < num_glyphs; i++) + { + if (entries[i] == NULL + || entries[i]->image == NULL) continue; x = (int) floor (glyphs[i].x + 0.5); y = (int) floor (glyphs[i].y + 0.5); - _cairo_pattern_init_for_surface (&glyph_pattern, &(img->image->base)); + _cairo_pattern_init_for_surface (&glyph_pattern, &(entries[i]->image->base)); - status = _cairo_surface_composite (operator, pattern, + status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, pattern, &glyph_pattern.base, - surface, - x + img->size.x, - y + img->size.y, + mask, + x + entries[i]->size.x, + y + entries[i]->size.y, 0, 0, - x + img->size.x, - y + img->size.y, - (double) img->size.width, - (double) img->size.height); + x + entries[i]->size.x - dest_x, + y + entries[i]->size.y - dest_y, + entries[i]->size.width, + entries[i]->size.height); _cairo_pattern_fini (&glyph_pattern.base); - if (status) { - _cairo_unlock_global_image_glyph_cache (); - return status; - } - } + if (status) + goto CLEANUP_MASK; + } + + _cairo_pattern_init_for_surface (&mask_pattern, mask); + + status = _cairo_surface_composite (operator, pattern, &mask_pattern.base, + surface, + source_x, source_y, + 0, 0, + dest_x, dest_y, + width, height); + + _cairo_pattern_fini (&mask_pattern.base); + + CLEANUP_MASK: + cairo_surface_destroy (mask); + + CLEANUP_ENTRIES: + free (entries); + CLEANUP_CACHE: _cairo_unlock_global_image_glyph_cache (); - return CAIRO_STATUS_SUCCESS; + return status; } @@ -2018,26 +2147,26 @@ _cairo_ft_scaled_font_glyph_path (void *abstract_font, } const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { - _cairo_ft_scaled_font_create, - _cairo_ft_scaled_font_destroy, + _cairo_ft_scaled_font_create_toy, + _cairo_ft_scaled_font_fini, _cairo_ft_scaled_font_font_extents, _cairo_ft_scaled_font_text_to_glyphs, _cairo_ft_scaled_font_glyph_extents, _cairo_ft_scaled_font_glyph_bbox, _cairo_ft_scaled_font_show_glyphs, _cairo_ft_scaled_font_glyph_path, - _cairo_ft_scaled_font_get_glyph_cache_key, + _cairo_ft_scaled_font_get_glyph_cache_key }; /* ft_font_face_t */ static void -_ft_font_face_destroy (void *abstract_face) +_cairo_ft_font_face_destroy (void *abstract_face) { - ft_font_face_t *font_face = abstract_face; + cairo_ft_font_face_t *font_face = abstract_face; - ft_font_face_t *tmp_face = NULL; - ft_font_face_t *last_face = NULL; + cairo_ft_font_face_t *tmp_face = NULL; + cairo_ft_font_face_t *last_face = NULL; if (font_face == NULL) return; @@ -2069,12 +2198,15 @@ _ft_font_face_destroy (void *abstract_face) if (font_face->unscaled) { /* Remove face from linked list */ - for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) { + for (tmp_face = font_face->unscaled->faces; + tmp_face; + tmp_face = tmp_face->next) + { if (tmp_face == font_face) { if (last_face) - last_face->next_face = tmp_face->next_face; + last_face->next = tmp_face->next; else - font_face->unscaled->faces = tmp_face->next_face; + font_face->unscaled->faces = tmp_face->next; } last_face = tmp_face; @@ -2086,13 +2218,13 @@ _ft_font_face_destroy (void *abstract_face) } static cairo_status_t -_ft_font_face_create_font (void *abstract_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **scaled_font) +_cairo_ft_font_face_scaled_font_create (void *abstract_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **scaled_font) { - ft_font_face_t *font_face = abstract_face; + cairo_ft_font_face_t *font_face = abstract_face; int load_flags; /* The handling of font options is different depending on how the @@ -2109,36 +2241,37 @@ _ft_font_face_create_font (void *abstract_face, else load_flags = font_face->load_flags; - *scaled_font = _ft_scaled_font_create (font_face->unscaled, - font_matrix, ctm, - options, load_flags); + *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled, + font_matrix, ctm, + options, load_flags); if (*scaled_font) return CAIRO_STATUS_SUCCESS; else return CAIRO_STATUS_NO_MEMORY; } -static const cairo_font_face_backend_t _ft_font_face_backend = { - _ft_font_face_destroy, - _ft_font_face_create_font, +static const cairo_font_face_backend_t _cairo_ft_font_face_backend = { + _cairo_ft_font_face_destroy, + _cairo_ft_font_face_scaled_font_create }; static cairo_font_face_t * -_ft_font_face_create (ft_unscaled_font_t *unscaled, - int load_flags) +_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, + int load_flags) { - ft_font_face_t *font_face; + cairo_ft_font_face_t *font_face; /* Looked for an existing matching font face */ - for (font_face = unscaled->faces; font_face; font_face = font_face->next_face) { - if (font_face->load_flags == load_flags) { - cairo_font_face_reference (&font_face->base); - return &font_face->base; - } + for (font_face = unscaled->faces; + font_face; + font_face = font_face->next) + { + if (font_face->load_flags == load_flags) + return cairo_font_face_reference (&font_face->base); } /* No match found, create a new one */ - font_face = malloc (sizeof (ft_font_face_t)); + font_face = malloc (sizeof (cairo_ft_font_face_t)); if (!font_face) return NULL; @@ -2147,10 +2280,10 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled, font_face->load_flags = load_flags; - font_face->next_face = unscaled->faces; + font_face->next = unscaled->faces; unscaled->faces = font_face; - _cairo_font_face_init (&font_face->base, &_ft_font_face_backend); + _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend); return &font_face->base; } @@ -2272,16 +2405,17 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options, cairo_font_face_t * cairo_ft_font_face_create_for_pattern (FcPattern *pattern) { - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; - unscaled = _ft_unscaled_font_get_for_pattern (pattern); + unscaled = _cairo_ft_unscaled_font_get_for_pattern (pattern); if (unscaled == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } - font_face = _ft_font_face_create (unscaled, _get_pattern_load_flags (pattern)); + font_face = _cairo_ft_font_face_create (unscaled, + _get_pattern_load_flags (pattern)); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) @@ -2321,16 +2455,16 @@ cairo_font_face_t * cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags) { - ft_unscaled_font_t *unscaled; + cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; - unscaled = _ft_unscaled_font_create_from_face (face); + unscaled = _cairo_ft_unscaled_font_create_from_face (face); if (unscaled == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } - font_face = _ft_font_face_create (unscaled, load_flags); + font_face = _cairo_ft_font_face_create (unscaled, load_flags); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) { @@ -2379,13 +2513,13 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font) if (scaled_font->base.status) return NULL; - face = _ft_unscaled_font_lock_face (scaled_font->unscaled); + face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled); if (face == NULL) { _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY); return NULL; } - _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale); + _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale); return face; } @@ -2408,7 +2542,7 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font) if (scaled_font->base.status) return; - _ft_unscaled_font_unlock_face (scaled_font->unscaled); + _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); } /* We expose our unscaled font implementation internally for the the @@ -2423,17 +2557,15 @@ _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font) return &scaled_font->unscaled->base; } -/* This differs from _cairo_ft_scaled_font_lock_face in that it doesn't - * set the scale on the face, but just returns it at the last scale. - */ -FT_Face -_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font) -{ - return _ft_unscaled_font_lock_face ((ft_unscaled_font_t *)unscaled_font); -} - void -_cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font) +_cairo_ft_font_reset_static_data (void) { - _ft_unscaled_font_unlock_face ((ft_unscaled_font_t *)unscaled_font); + _lock_global_ft_cache (); + if (_global_ft_cache) { + FT_Done_FreeType (_global_ft_cache->lib); + _global_ft_cache->lib = NULL; + } + _cairo_cache_destroy (&_global_ft_cache->base); + _global_ft_cache = NULL; + _unlock_global_ft_cache (); } |