diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -101,6 +101,24 @@ */ #define MAX_OPEN_FACES 10 +extern void mozilla_AddRefSharedFTFace(void* aContext); +extern void mozilla_ReleaseSharedFTFace(void* aContext, void* aOwner); +/* Returns true if the face's state has been modified by another owner. */ +extern int mozilla_LockSharedFTFace(void* aContext, void* aOwner); +extern void mozilla_UnlockSharedFTFace(void* aContext); +extern FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags); +extern void mozilla_LockFTLibrary(FT_Library aLibrary); +extern void mozilla_UnlockFTLibrary(FT_Library aLibrary); + +#define CAIRO_FT_LOCK(unscaled) \ + ((unscaled)->face_context \ + ? (void)mozilla_LockSharedFTFace((unscaled)->face_context, NULL) \ + : (void)CAIRO_MUTEX_LOCK((unscaled)->mutex)) +#define CAIRO_FT_UNLOCK(unscaled) \ + ((unscaled)->face_context \ + ? mozilla_UnlockSharedFTFace((unscaled)->face_context) \ + : (void)CAIRO_MUTEX_UNLOCK((unscaled)->mutex)) + /** * SECTION:cairo-ft * @Title: FreeType Fonts @@ -154,6 +172,7 @@ struct _cairo_ft_unscaled_font { cairo_bool_t from_face; /* was the FT_Face provided by user? */ FT_Face face; /* provided or cached face */ + void *face_context; /* only set if from_face is false */ char *filename; @@ -336,7 +355,9 @@ static void _cairo_hash_table_remove (font_map->hash_table, &unscaled->base.hash_entry); - if (! unscaled->from_face) + if (unscaled->from_face) + mozilla_ReleaseSharedFTFace (unscaled->face_context, unscaled); + else _font_map_release_face_lock_held (font_map, unscaled); _cairo_ft_unscaled_font_fini (unscaled); @@ -395,7 +416,8 @@ static void cairo_bool_t from_face, char *filename, int id, - FT_Face face) + FT_Face face, + void *face_context) { unsigned long hash; @@ -403,6 +425,7 @@ static void key->filename = filename; key->id = id; key->face = face; + key->face_context = face_context; hash = _cairo_hash_string (filename); /* the constants are just arbitrary primes */ @@ -438,7 +461,8 @@ static cairo_status_t cairo_bool_t from_face, const char *filename, int id, - FT_Face face) + FT_Face face, + void *face_context) { _cairo_unscaled_font_init (&unscaled->base, &cairo_ft_unscaled_font_backend); @@ -447,7 +471,7 @@ static cairo_status_t if (from_face) { unscaled->from_face = TRUE; - _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, id, face); + _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, id, face, face_context); unscaled->have_color = FT_HAS_COLOR (face) != 0; @@ -474,12 +498,13 @@ static cairo_status_t unscaled->from_face = FALSE; unscaled->face = NULL; + unscaled->face_context = NULL; filename_copy = strdup (filename); if (unlikely (filename_copy == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL); + _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL, NULL); unscaled->have_color_set = FALSE; } @@ -528,7 +553,8 @@ static int unscaled_a->from_face == unscaled_b->from_face) { if (unscaled_a->from_face) - return unscaled_a->face == unscaled_b->face; + return unscaled_a->face == unscaled_b->face && + unscaled_a->face_context == unscaled_b->face_context; if (unscaled_a->filename == NULL && unscaled_b->filename == NULL) return TRUE; @@ -549,6 +575,7 @@ static cairo_status_t char *filename, int id, FT_Face font_face, + void *face_context, cairo_ft_unscaled_font_t **out) { cairo_ft_unscaled_font_t key, *unscaled; @@ -559,7 +586,7 @@ static cairo_status_t if (unlikely (font_map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face); + _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face, face_context); /* Return existing unscaled font if it exists in the hash table. */ unscaled = _cairo_hash_table_lookup (font_map->hash_table, @@ -576,7 +603,7 @@ static cairo_status_t goto UNWIND_FONT_MAP_LOCK; } - status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face); + status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face, face_context); if (unlikely (status)) goto UNWIND_UNSCALED_MALLOC; @@ -586,6 +613,8 @@ static cairo_status_t if (unlikely (status)) goto UNWIND_UNSCALED_FONT_INIT; + mozilla_AddRefSharedFTFace (face_context); + DONE: _cairo_ft_unscaled_font_map_unlock (); *out = unscaled; @@ -638,16 +667,17 @@ static cairo_status_t DONE: return _cairo_ft_unscaled_font_create_internal (font_face != NULL, - filename, id, font_face, + filename, id, font_face, NULL, out); } #endif static cairo_status_t _cairo_ft_unscaled_font_create_from_face (FT_Face face, + void *face_context, cairo_ft_unscaled_font_t **out) { - return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, face->face_index, face, out); + return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, face->face_index, face, face_context, out); } static cairo_bool_t @@ -675,12 +705,16 @@ static cairo_bool_t */ if (unscaled->faces && unscaled->faces->unscaled == NULL) { assert (unscaled->faces->next == NULL); + CAIRO_FT_LOCK (unscaled); cairo_font_face_destroy (&unscaled->faces->base); + CAIRO_FT_UNLOCK (unscaled); } + mozilla_ReleaseSharedFTFace (unscaled->face_context, unscaled); } else { _font_map_release_face_lock_held (font_map, unscaled); } unscaled->face = NULL; + unscaled->face_context = NULL; _cairo_ft_unscaled_font_map_unlock (); @@ -709,7 +743,13 @@ static cairo_warn FT_Face FT_Face face = NULL; FT_Error error; - CAIRO_MUTEX_LOCK (unscaled->mutex); + if (unscaled->face_context) { + if (!mozilla_LockSharedFTFace (unscaled->face_context, unscaled)) { + unscaled->have_scale = FALSE; + } + } else { + CAIRO_FT_LOCK (unscaled); + } unscaled->lock_count++; if (unscaled->face) @@ -744,7 +784,7 @@ static cairo_warn FT_Face if (error) { unscaled->lock_count--; - CAIRO_MUTEX_UNLOCK (unscaled->mutex); + CAIRO_FT_UNLOCK (unscaled); _cairo_error_throw (_ft_to_cairo_error (error)); return NULL; } @@ -769,7 +809,7 @@ static void unscaled->lock_count--; - CAIRO_MUTEX_UNLOCK (unscaled->mutex); + CAIRO_FT_UNLOCK (unscaled); } @@ -3164,19 +3204,21 @@ static cairo_bool_t * font_face <------- unscaled */ - if (font_face->unscaled && - font_face->unscaled->from_face && - font_face->next == NULL && - font_face->unscaled->faces == font_face && - CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1) - { - _cairo_unscaled_font_destroy (&font_face->unscaled->base); - font_face->unscaled = NULL; - - return FALSE; - } - if (font_face->unscaled) { + CAIRO_FT_LOCK (font_face->unscaled); + + if (font_face->unscaled->from_face && + font_face->next == NULL && + font_face->unscaled->faces == font_face && + CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1) + { + CAIRO_FT_UNLOCK (font_face->unscaled); + _cairo_unscaled_font_destroy (&font_face->unscaled->base); + font_face->unscaled = NULL; + + return FALSE; + } + cairo_ft_font_face_t *tmp_face = NULL; cairo_ft_font_face_t *last_face = NULL; @@ -3195,6 +3237,7 @@ static cairo_bool_t last_face = tmp_face; } + CAIRO_FT_UNLOCK (font_face->unscaled); _cairo_unscaled_font_destroy (&font_face->unscaled->base); font_face->unscaled = NULL; } @@ -3268,6 +3311,24 @@ static cairo_font_face_t * return abstract_face; } +static void +_cairo_ft_font_face_lock (void *abstract_face) +{ + cairo_ft_font_face_t *font_face = abstract_face; + if (font_face->unscaled) { + CAIRO_FT_LOCK (font_face->unscaled); + } +} + +static void +_cairo_ft_font_face_unlock (void *abstract_face) +{ + cairo_ft_font_face_t *font_face = abstract_face; + if (font_face->unscaled) { + CAIRO_FT_UNLOCK (font_face->unscaled); + } +} + const cairo_font_face_backend_t _cairo_ft_font_face_backend = { CAIRO_FONT_TYPE_FT, #if CAIRO_HAS_FC_FONT @@ -3277,7 +3338,11 @@ const cairo_font_face_backend_t _cairo_f #endif _cairo_ft_font_face_destroy, _cairo_ft_font_face_scaled_font_create, - _cairo_ft_font_face_get_implementation + _cairo_ft_font_face_get_implementation, +/* + _cairo_ft_font_face_lock, + _cairo_ft_font_face_unlock +*/ }; #if CAIRO_HAS_FC_FONT @@ -3320,6 +3385,8 @@ static cairo_font_face_t * { cairo_ft_font_face_t *font_face, **prev_font_face; + CAIRO_FT_LOCK (unscaled); + /* Looked for an existing matching font face */ for (font_face = unscaled->faces, prev_font_face = &unscaled->faces; font_face; @@ -3341,15 +3408,19 @@ static cairo_font_face_t * * from owner to ownee. */ font_face->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); - return &font_face->base; - } else - return cairo_font_face_reference (&font_face->base); + } else { + cairo_font_face_reference (&font_face->base); + } + + CAIRO_FT_UNLOCK (unscaled); + return &font_face->base; } } /* No match found, create a new one */ font_face = _cairo_malloc (sizeof (cairo_ft_font_face_t)); if (unlikely (!font_face)) { + CAIRO_FT_UNLOCK (unscaled); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } @@ -3376,6 +3447,7 @@ static cairo_font_face_t * _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend); + CAIRO_FT_UNLOCK (unscaled); return &font_face->base; } @@ -3737,14 +3809,16 @@ cairo_ft_font_face_create_for_pattern (F cairo_font_face_t * cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags, - unsigned int synth_flags) + unsigned int synth_flags, + void *face_context) { cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; cairo_ft_options_t ft_options; cairo_status_t status; - status = _cairo_ft_unscaled_font_create_from_face (face, &unscaled); + status = _cairo_ft_unscaled_font_create_from_face (face, face_context, + &unscaled); if (unlikely (status)) return (cairo_font_face_t *)&_cairo_font_face_nil; @@ -3896,7 +3970,7 @@ cairo_ft_scaled_font_lock_face (cairo_sc * opportunity for creating deadlock. This is obviously unsafe, * but as documented, the user must add manual locking when using * this function. */ - CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex); + CAIRO_FT_UNLOCK (scaled_font->unscaled); return face; } @@ -3929,7 +4003,7 @@ cairo_ft_scaled_font_unlock_face (cairo_ * cairo_ft_scaled_font_lock_face, so we have to acquire it again * as _cairo_ft_unscaled_font_unlock_face expects it to be held * when we call into it. */ - CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex); + CAIRO_FT_LOCK (scaled_font->unscaled); _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); } diff --git a/gfx/cairo/cairo/src/cairo-ft.h b/gfx/cairo/cairo/src/cairo-ft.h --- a/gfx/cairo/cairo/src/cairo-ft.h +++ b/gfx/cairo/cairo/src/cairo-ft.h @@ -55,7 +55,8 @@ CAIRO_BEGIN_DECLS cairo_public cairo_font_face_t * cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags, - unsigned int synth_flags); + unsigned int synth_flags, + void *face_context); /** * cairo_ft_synthesize_t: