summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2008-10-21 22:48:17 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2008-10-22 00:53:55 +0100
commit1db8949f2baf1e620e1d5ef73a66de211420bd0a (patch)
tree23f0a27e6a92ec287be86e7f52e8d68b2aa886d3
parentb2cbbceb4ca57816a498c2c1e676b19182c34e12 (diff)
Ensure that the scaled font is frozen for the lifetime of the scaled glyph.
After discussing the scaled font locking with Behdad, it transpired that it is not sufficient for a font to be locked for the lifetime of a scaled glyph, but that the scaled font's glyph cache must be frozen for the glyph' lifetime. If the cache is not frozen, then there is a possibility that the glyph may be evicted before the reference goes out of scope i.e. the glyph becomes invalid whilst we are trying to use it. Since the freezing of the cache is the stronger barrier, we remove the locking/unlocking of the mutex from the backends and instead move the mutex acquisition into the freeze/thaw routines. Then update the rule on acquiring glyphs to enforce that the cache is frozen and review the usage of freeze/thaw by all the backends to ensure that the cache is frozen for the lifetime of the glyph.
-rw-r--r--src/cairo-directfb-surface.c4
-rw-r--r--src/cairo-glitz-surface.c2
-rw-r--r--src/cairo-gstate.c4
-rw-r--r--src/cairo-meta-surface.c2
-rw-r--r--src/cairo-mutex-impl-private.h3
-rw-r--r--src/cairo-mutex-type-private.h3
-rw-r--r--src/cairo-paginated-surface.c2
-rw-r--r--src/cairo-pdf-surface.c2
-rw-r--r--src/cairo-scaled-font-subsets.c30
-rw-r--r--src/cairo-scaled-font.c81
-rw-r--r--src/cairo-surface-fallback.c1
-rw-r--r--src/cairo-surface.c4
-rw-r--r--src/cairo-svg-surface.c4
-rw-r--r--src/cairo-type1-fallback.c9
-rw-r--r--src/cairo-type3-glyph-surface.c18
-rw-r--r--src/cairo-user-font.c1
-rw-r--r--src/cairo-win32-font.c12
-rw-r--r--src/cairo-xcb-surface.c216
-rw-r--r--src/cairo-xlib-surface.c57
-rw-r--r--src/cairoint.h4
-rw-r--r--src/test-meta-surface.c25
-rw-r--r--src/test-paginated-surface.c25
22 files changed, 280 insertions, 229 deletions
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index 662448e1..aa67b023 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1432,14 +1432,14 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs );
+ _cairo_cache_freeze (scaled_font->glyphs);
+
if (scaled_font->surface_private) {
cache = scaled_font->surface_private;
x = cache->x;
y = cache->y;
}
- _cairo_cache_freeze (scaled_font->glyphs);
-
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
cairo_image_surface_t *img;
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 9a148bf8..784bff98 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -2020,7 +2020,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
if (scaled_font->surface_private == NULL)
{
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index e9387f5a..00f498e0 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1615,11 +1615,9 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
_cairo_path_fixed_init (&path);
- CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
&path);
- CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (gstate->target,
@@ -1670,11 +1668,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
if (status)
goto CLEANUP_GLYPHS;
- CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
path);
- CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index f45bdb95..b86cb513 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -730,12 +730,10 @@ _cairo_meta_surface_get_path (cairo_surface_t *surface,
}
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
{
- CAIRO_MUTEX_LOCK (command->show_text_glyphs.scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
command->show_text_glyphs.glyphs,
command->show_text_glyphs.num_glyphs,
path);
- CAIRO_MUTEX_UNLOCK (command->show_text_glyphs.scaled_font->mutex);
break;
}
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
index 3e196164..239dbbb0 100644
--- a/src/cairo-mutex-impl-private.h
+++ b/src/cairo-mutex-impl-private.h
@@ -181,7 +181,8 @@
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
#if HAVE_LOCKDEP
-# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_HOLDS_LOCK (&(mutex))
+# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex))
+# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex))
#endif
# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
#if ! HAVE_LOCKDEP
diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h
index 040e99f6..adf17bbe 100644
--- a/src/cairo-mutex-type-private.h
+++ b/src/cairo-mutex-type-private.h
@@ -171,6 +171,9 @@ typedef cairo_mutex_impl_t cairo_mutex_t;
#ifndef CAIRO_MUTEX_IS_LOCKED
# define CAIRO_MUTEX_IS_LOCKED(name) 1
#endif
+#ifndef CAIRO_MUTEX_IS_UNLOCKED
+# define CAIRO_MUTEX_IS_UNLOCKED(name) 1
+#endif
/* Debugging support */
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 97a1f210..a94ca80a 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -637,14 +637,12 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
* show_glyphs functions, (which would get less testing and likely
* lead to bugs).
*/
- CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
cluster_flags,
scaled_font);
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
return status;
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index b07ee98d..2823508a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4050,14 +4050,12 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
&group->ctm_inverse);
break;
case PDF_SHOW_GLYPHS:
- CAIRO_MUTEX_LOCK (group->scaled_font->mutex);
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
group->utf8, group->utf8_len,
group->glyphs, group->num_glyphs,
group->clusters, group->num_clusters,
group->cluster_flags,
group->scaled_font);
- CAIRO_MUTEX_UNLOCK (group->scaled_font->mutex);
break;
}
if (status)
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 3bf90738..f5212d7a 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -445,12 +445,13 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
- cairo_scaled_glyph_t *scaled_glyph;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
(cairo_hash_entry_t **) &sub_font_glyph))
{
+ cairo_scaled_glyph_t *scaled_glyph;
+
if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
{
cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
@@ -464,19 +465,24 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
return status;
}
+ _cairo_scaled_font_freeze_cache (sub_font->scaled_font);
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
- if (status)
+ if (status) {
+ _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
return status;
+ }
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset,
scaled_glyph->metrics.x_advance,
scaled_glyph->metrics.y_advance);
+ _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
+
if (sub_font_glyph == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -702,10 +708,12 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (scaled_font_glyph_index == 0) {
status = CAIRO_STATUS_SUCCESS;
} else {
+ _cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_scaled_glyph_lookup (scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
+ _cairo_scaled_font_thaw_cache (scaled_font);
}
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -745,7 +753,6 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
subset_glyph->is_composite = FALSE;
}
- CAIRO_MUTEX_LOCK (unscaled_font->mutex);
status = _cairo_sub_font_create (subsets,
unscaled_font,
subsets->num_sub_fonts,
@@ -753,7 +760,6 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
subset_glyph->is_scaled,
subset_glyph->is_composite,
&sub_font);
- CAIRO_MUTEX_UNLOCK (unscaled_font->mutex);
if (status) {
cairo_scaled_font_destroy (unscaled_font);
@@ -815,18 +821,10 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
}
}
- if (sub_font->scaled_font != scaled_font)
- CAIRO_MUTEX_LOCK (sub_font->scaled_font->mutex);
-
- status = _cairo_sub_font_map_glyph (sub_font,
- scaled_font_glyph_index,
- utf8, utf8_len,
- subset_glyph);
-
- if (sub_font->scaled_font != scaled_font)
- CAIRO_MUTEX_UNLOCK (sub_font->scaled_font->mutex);
-
- return status;
+ return _cairo_sub_font_map_glyph (sub_font,
+ scaled_font_glyph_index,
+ utf8, utf8_len,
+ subset_glyph);
}
static cairo_status_t
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 83a3927a..d312a4c8 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -145,6 +145,9 @@
* and note that glyph origin = device-space origin.
*/
+static void
+_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font);
+
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
@@ -377,11 +380,11 @@ _cairo_scaled_font_map_destroy (void)
font_map->num_holdovers--;
- /* release the lock to avoid the possibility of a recursive
- * deadlock when the scaled font destroy closure gets called */
- CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
+ /* This releases the font_map lock to avoid the possibility of a
+ * recursive deadlock when the scaled font destroy closure gets
+ * called
+ */
_cairo_scaled_font_fini (scaled_font);
- CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
free (scaled_font);
}
@@ -451,7 +454,7 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t
return CAIRO_STATUS_SUCCESS;
FINI_PLACEHOLDER:
- _cairo_scaled_font_fini (placeholder_scaled_font);
+ _cairo_scaled_font_fini_internal (placeholder_scaled_font);
FREE_PLACEHOLDER:
free (placeholder_scaled_font);
@@ -498,8 +501,9 @@ _cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t
/* ok, creation done. just clean up and back out */
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
- CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
cairo_scaled_font_destroy (placeholder_scaled_font);
+
+ CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
@@ -656,17 +660,18 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
void
_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
{
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
+ /* ensure we do not modify an error object */
+ assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
+ CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_cache_freeze (scaled_font->glyphs);
}
void
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
{
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
-
_cairo_cache_thaw (scaled_font->glyphs);
+ CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
void
@@ -707,8 +712,8 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
-void
-_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
+static void
+_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
{
scaled_font->finished = TRUE;
@@ -730,6 +735,16 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
_cairo_user_data_array_fini (&scaled_font->user_data);
}
+void
+_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
+{
+ /* Release the lock to avoid the possibility of a recursive
+ * deadlock when the scaled font destroy closure gets called. */
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
+ _cairo_scaled_font_fini_internal (scaled_font);
+ CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
+}
+
/**
* cairo_scaled_font_create:
* @font_face: a #cairo_font_face_t
@@ -881,7 +896,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
/* We can't call _cairo_scaled_font_destroy here since it expects
* that the font has already been successfully inserted into the
* hash table. */
- _cairo_scaled_font_fini (scaled_font);
+ _cairo_scaled_font_fini_internal (scaled_font);
free (scaled_font);
return _cairo_scaled_font_create_in_error (status);
}
@@ -985,6 +1000,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
cairo_scaled_font_t *lru = NULL;
cairo_scaled_font_map_t *font_map;
+ assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex));
+
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return;
@@ -1025,7 +1042,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
}
- CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
+ _cairo_scaled_font_map_unlock ();
/* If we pulled an item from the holdovers array, (while the font
* map lock was held, of course), then there is no way that anyone
@@ -1034,7 +1051,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* as we never want to call into any backend function with a lock
* held. */
if (lru) {
- _cairo_scaled_font_fini (lru);
+ _cairo_scaled_font_fini_internal (lru);
free (lru);
}
}
@@ -1114,6 +1131,13 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
key, user_data, destroy);
}
+static cairo_bool_t
+_cairo_scaled_font_is_frozen (cairo_scaled_font_t *scaled_font)
+{
+ return CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex) &&
+ scaled_font->glyphs->freeze_count > 0;
+}
+
/* Public font API follows. */
/**
@@ -1257,7 +1281,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
return;
}
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
@@ -1326,7 +1349,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
UNLOCK:
_cairo_scaled_font_thaw_cache (scaled_font);
- CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
slim_hidden_def (cairo_scaled_font_glyph_extents);
@@ -1551,7 +1573,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
goto BAIL;
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
orig_glyphs = *glyphs;
@@ -1657,7 +1678,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
DONE: /* error that should be logged on scaled_font happened */
_cairo_scaled_font_thaw_cache (scaled_font);
- CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
if (status) {
*num_glyphs = 0;
@@ -1706,7 +1726,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
if (scaled_font->status)
return scaled_font->status;
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
+ _cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
@@ -1719,7 +1739,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
- return _cairo_scaled_font_set_error (scaled_font, status);
+ break;
/* XXX glyph images are snapped to pixel locations */
x = _cairo_lround (glyphs[i].x);
@@ -1735,6 +1755,11 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
if (top < min.y) min.y = top;
if (bottom > max.y) max.y = bottom;
}
+
+ _cairo_scaled_font_thaw_cache (scaled_font);
+ if (status)
+ return _cairo_scaled_font_set_error (scaled_font, status);
+
if (min.x < max.x && min.y < max.y) {
extents->x = min.x;
extents->width = max.x - min.x;
@@ -1744,6 +1769,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
extents->x = extents->y = 0;
extents->width = extents->height = 0;
}
+
return CAIRO_STATUS_SUCCESS;
}
@@ -1779,7 +1805,6 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
if (!num_glyphs)
return CAIRO_STATUS_SUCCESS;
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
if (scaled_font->backend->show_glyphs != NULL) {
int remaining_glyphs = num_glyphs;
status = scaled_font->backend->show_glyphs (scaled_font,
@@ -1801,7 +1826,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
- _cairo_cache_freeze (scaled_font->glyphs);
+ _cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
int x, y;
@@ -1921,7 +1946,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_fini (&mask_pattern.base);
CLEANUP_MASK:
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
_cairo_pattern_fini (&white_pattern.base);
@@ -2094,8 +2119,6 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
if (status)
return status;
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
-
closure.path = path;
_cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
@@ -2282,7 +2305,11 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
* get INFO_PATH with a bitmapped font), this function will return
* %CAIRO_INT_STATUS_UNSUPPORTED.
*
- * Note: This function must be called with scaled_font->mutex held.
+ * Note: This function must be called with the scaled font frozen, and it must
+ * remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled
+ * font was not frozen, then there is no guarantee that the glyph would not be
+ * evicted before you tried to access it.) See
+ * _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache().
*
* Returns: a glyph with the requested portions filled in. Glyph
* lookup is cached and glyph will be automatically freed along
@@ -2306,7 +2333,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
if (scaled_font->status)
return scaled_font->status;
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
+ assert (_cairo_scaled_font_is_frozen (scaled_font));
key.hash = index;
/*
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 8bafb346..c44dfafa 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -988,6 +988,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t glyph_extents;
+
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 75cccaeb..d1df1869 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2267,8 +2267,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
- CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
@@ -2328,8 +2326,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
glyphs, num_glyphs,
dev_scaled_font);
- CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex);
-
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 1219d18f..f392c8ed 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -739,7 +739,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
unsigned int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- CAIRO_MUTEX_LOCK (font_subset->scaled_font->mutex);
+ _cairo_scaled_font_freeze_cache (font_subset->scaled_font);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_svg_document_emit_glyph (document,
font_subset->scaled_font,
@@ -748,7 +748,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
if (status)
break;
}
- CAIRO_MUTEX_UNLOCK (font_subset->scaled_font->mutex);
+ _cairo_scaled_font_thaw_cache (font_subset->scaled_font);
return status;
}
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 840fc7d1..83ddc448 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -348,7 +348,6 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
cairo_bool_t emit_path = TRUE;
/* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
- CAIRO_MUTEX_LOCK (font->type1_scaled_font->mutex);
status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS|
@@ -364,7 +363,6 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
}
- CAIRO_MUTEX_UNLOCK (font->type1_scaled_font->mutex);
if (status)
return status;
@@ -446,18 +444,21 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
"2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1);
+ _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
+
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE1,
&data);
if (status)
goto fail;
+
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
if (font->scaled_font_subset->glyph_names != NULL) {
@@ -476,6 +477,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
}
fail:
+ _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
_cairo_array_fini (&data);
return status;
}
@@ -825,6 +827,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
goto fail1;
}
+ _cairo_scaled_font_freeze_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_init (&charstring, sizeof (unsigned char));
status = _cairo_array_grow_by (&charstring, 32);
@@ -842,6 +845,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
if (status)
goto fail2;
}
+ _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
type2_subset->widths[i] = font->widths[i];
@@ -856,6 +860,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
return cairo_type1_font_destroy (font);
fail2:
+ _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
_cairo_array_fini (&charstring);
_cairo_type2_charstrings_fini (type2_subset);
fail1:
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 3508ce72..ed8fff7f 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -286,14 +286,12 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
&new_ctm,
&scaled_font->options);
- CAIRO_MUTEX_LOCK (font->mutex);
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
font);
- CAIRO_MUTEX_UNLOCK (font->mutex);
cairo_scaled_font_destroy (font);
@@ -349,13 +347,11 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
cairo_matrix_t mat;
double x, y;
- CAIRO_MUTEX_LOCK (surface->scaled_font->mutex);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
- CAIRO_MUTEX_UNLOCK (surface->scaled_font->mutex);
if (status)
return status;
@@ -401,13 +397,12 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
null_stream = _cairo_null_stream_create ();
_cairo_type3_glyph_surface_set_stream (surface, null_stream);
- CAIRO_MUTEX_LOCK (surface->scaled_font->mutex);
+ _cairo_scaled_font_freeze_cache (surface->scaled_font);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
&scaled_glyph);
- CAIRO_MUTEX_UNLOCK (surface->scaled_font->mutex);
if (_cairo_status_is_error (status))
goto cleanup;
@@ -430,6 +425,8 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
status = CAIRO_STATUS_SUCCESS;
cleanup:
+ _cairo_scaled_font_thaw_cache (surface->scaled_font);
+
status2 = _cairo_output_stream_destroy (null_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
@@ -469,7 +466,7 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_type3_glyph_surface_set_stream (surface, stream);
- CAIRO_MUTEX_LOCK (surface->scaled_font->mutex);
+ _cairo_scaled_font_freeze_cache (surface->scaled_font);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
@@ -483,9 +480,10 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
if (status == CAIRO_STATUS_SUCCESS)
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
- CAIRO_MUTEX_UNLOCK (surface->scaled_font->mutex);
- if (_cairo_status_is_error (status))
+ if (_cairo_status_is_error (status)) {
+ _cairo_scaled_font_thaw_cache (surface->scaled_font);
return status;
+ }
x_advance = scaled_glyph->metrics.x_advance;
y_advance = scaled_glyph->metrics.y_advance;
@@ -538,6 +536,8 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
+ _cairo_scaled_font_thaw_cache (surface->scaled_font);
+
return status;
}
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 5645287a..385b8414 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -481,7 +481,6 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
-
if (status != CAIRO_STATUS_SUCCESS) {
_cairo_scaled_font_fini (&user_scaled_font->base);
free (user_scaled_font);
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index f82d5288..dc937585 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -640,21 +640,25 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
- goto FAIL2;
+ goto FAIL3;
}
*num_glyphs = n16;
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
if (!*glyphs) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FAIL2;
+ goto FAIL3;
}
x_pos = x;
y_pos = y;
+
mat = scaled_font->base.ctm;
status = cairo_matrix_invert (&mat);
assert (status == CAIRO_STATUS_SUCCESS);
+
+ _cairo_scaled_font_freeze_cache (&scaled_font->base);
+
for (i = 0; i < n16; i++) {
cairo_scaled_glyph_t *scaled_glyph;
@@ -668,7 +672,7 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
&scaled_glyph);
if (status) {
free (*glyphs);
- goto FAIL2;
+ goto FAIL3;
}
x = scaled_glyph->x_advance;
@@ -678,6 +682,8 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
y_pos += y;
}
+FAIL3:
+ _cairo_scaled_font_thaw_cache (&scaled_font->base);
cairo_win32_scaled_font_done_font (&scaled_font->base);
FAIL2:
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 895d8e86..1760bcbc 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -2332,14 +2332,121 @@ typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t)
(cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int,
const cairo_glyph_t *, int, cairo_scaled_font_t *);
+static cairo_bool_t
+_cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_xcb_surface_font_private_t *font_private;
+
+ font_private = scaled_font->surface_private;
+ if ((scaled_font->surface_backend != NULL &&
+ scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
+ (font_private != NULL && font_private->dpy != dst->dpy))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+static cairo_status_t
+_cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ cairo_operator_t op,
+ cairo_xcb_surface_t *src,
+ cairo_surface_attributes_t *attributes,
+ int *remaining_glyphs)
+{
+ cairo_scaled_glyph_t *scaled_glyph;
+ int i, o;
+ unsigned long max_index = 0;
+ cairo_status_t status;
+ cairo_glyph_t *output_glyphs;
+ const cairo_glyph_t *glyphs_chunk;
+ int glyphs_remaining, chunk_size, max_chunk_size;
+ cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
+
+ /* We make a copy of the glyphs so that we can elide any size-zero
+ * glyphs to workaround an X server bug, (present in at least Xorg
+ * 7.1 without EXA). */
+ output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+ if (output_glyphs == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ for (i = 0, o = 0; i < num_glyphs; i++) {
+ if (glyphs[i].index > max_index)
+ max_index = glyphs[i].index;
+ status = _cairo_scaled_glyph_lookup (scaled_font,
+ glyphs[i].index,
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ &scaled_glyph);
+ if (status) {
+ free (output_glyphs);
+ return status;
+ }
+
+ /* Don't put any size-zero glyphs into output_glyphs to avoid
+ * an X server bug which stops rendering glyphs after the
+ * first size-zero glyph. */
+ if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
+ output_glyphs[o++] = glyphs[i];
+ if (scaled_glyph->surface_private == NULL) {
+ _cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
+ scaled_glyph->surface_private = (void *) 1;
+ }
+ }
+ }
+ num_glyphs = o;
+
+ _cairo_xcb_surface_ensure_dst_picture (dst);
+
+ max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
+ if (max_index < 256) {
+ /* XXX: these are all the same size! (28) */
+ max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
+ show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
+ } else if (max_index < 65536) {
+ max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
+ show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
+ } else {
+ max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
+ show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
+ }
+ /* XXX: I think this is wrong; this is only the header size (2 longs) */
+ /* but should also include the glyph (1 long) */
+ /* max_chunk_size /= sz_xGlyphElt; */
+ max_chunk_size /= 3*sizeof(uint32_t);
+
+ for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
+ glyphs_remaining;
+ glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
+ {
+ chunk_size = MIN (glyphs_remaining, max_chunk_size);
+
+ status = show_glyphs_func (dst, op, src,
+ attributes->x_offset, attributes->y_offset,
+ glyphs_chunk, chunk_size, scaled_font);
+ if (status) {
+ free (output_glyphs);
+ return status;
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static cairo_int_status_t
_cairo_xcb_surface_show_glyphs (void *abstract_dst,
- cairo_operator_t op,
- cairo_pattern_t *src_pattern,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- int *remaining_glyphs)
+ cairo_operator_t op,
+ cairo_pattern_t *src_pattern,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ int *remaining_glyphs)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_xcb_surface_t *dst = abstract_dst;
@@ -2348,17 +2455,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xcb_surface_t *src = NULL;
- cairo_glyph_t *output_glyphs;
- const cairo_glyph_t *glyphs_chunk;
- int glyphs_remaining, chunk_size, max_chunk_size;
- cairo_scaled_glyph_t *scaled_glyph;
- cairo_xcb_surface_font_private_t *font_private;
-
- int i, o;
- unsigned long max_index = 0;
-
- cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
-
cairo_solid_pattern_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
@@ -2392,29 +2488,16 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
- font_private = scaled_font->surface_private;
- if ((scaled_font->surface_backend != NULL &&
- scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
- (font_private != NULL && font_private->dpy != dst->dpy))
+ if (! _cairo_xcb_surface_owns_font (dst, scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
- /* We make a copy of the glyphs so that we can elide any size-zero
- * glyphs to workaround an X server bug, (present in at least Xorg
- * 7.1 without EXA). */
- output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
- if (output_glyphs == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
* them. We tie into the scaled_font's glyph cache and remove
* glyphs from the X server when they are ejected from the
- * scaled_font cache. Because of this we first freeze the
- * scaled_font's cache so that we don't cause any of our glyphs to
- * be ejected and removed from the X server before we have a
- * chance to render them. */
- _cairo_scaled_font_freeze_cache (scaled_font);
+ * scaled_font cache.
+ */
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
* the mask (the glyphs). This code below was executed as a side effect
@@ -2464,64 +2547,21 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
goto BAIL;
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
- for (i = 0, o = 0; i < num_glyphs; i++) {
- if (glyphs[i].index > max_index)
- max_index = glyphs[i].index;
- status = _cairo_scaled_glyph_lookup (scaled_font,
- glyphs[i].index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
- if (status != CAIRO_STATUS_SUCCESS)
- goto BAIL;
- /* Don't put any size-zero glyphs into output_glyphs to avoid
- * an X server bug which stops rendering glyphs after the
- * first size-zero glyph. */
- if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
- output_glyphs[o++] = glyphs[i];
- if (scaled_glyph->surface_private == NULL) {
- _cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
- scaled_glyph->surface_private = (void *) 1;
- }
- }
- }
- num_glyphs = o;
-
- _cairo_xcb_surface_ensure_dst_picture (dst);
-
- max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
- if (max_index < 256) {
- /* XXX: these are all the same size! (28) */
- max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
- show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
- } else if (max_index < 65536) {
- max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
- show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
- } else {
- max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
- show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
- }
- /* XXX: I think this is wrong; this is only the header size (2 longs) */
- /* but should also include the glyph (1 long) */
- /* max_chunk_size /= sz_xGlyphElt; */
- max_chunk_size /= 3*sizeof(uint32_t);
-
- for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
- glyphs_remaining;
- glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
- {
- chunk_size = MIN (glyphs_remaining, max_chunk_size);
-
- status = show_glyphs_func (dst, op, src,
- attributes.x_offset, attributes.y_offset,
- glyphs_chunk, chunk_size, scaled_font);
- if (status != CAIRO_STATUS_SUCCESS)
- break;
- }
+ _cairo_scaled_font_freeze_cache (scaled_font);
- BAIL:
+ if (_cairo_xcb_surface_owns_font (dst, scaled_font))
+ status = _cairo_xcb_surface_emit_glyphs (dst,
+ glyphs, num_glyphs,
+ scaled_font,
+ op,
+ src,
+ &attributes,
+ remaining_glyphs);
+ else
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_scaled_font_thaw_cache (scaled_font);
- free (output_glyphs);
+ BAIL:
if (src)
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
if (src_pattern == &solid_pattern.base)
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 7bf34ee9..ac840b80 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -3107,7 +3107,7 @@ _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display,
scaled_font = font_private->scaled_font;
CAIRO_MUTEX_LOCK (scaled_font->mutex);
- font_private = scaled_font->surface_private;
+ font_private = scaled_font->surface_private;
scaled_font->surface_private = NULL;
_cairo_scaled_font_reset_cache (scaled_font);
@@ -3936,6 +3936,23 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
return status;
}
+static cairo_bool_t
+_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_xlib_surface_font_private_t *font_private;
+
+ font_private = scaled_font->surface_private;
+ if ((scaled_font->surface_backend != NULL &&
+ scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
+ (font_private != NULL && font_private->display != dst->display))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
@@ -3952,8 +3969,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xlib_surface_t *src = NULL;
- cairo_xlib_surface_font_private_t *font_private;
-
cairo_solid_pattern_t solid_pattern;
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
@@ -3987,22 +4002,14 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
- font_private = scaled_font->surface_private;
- if ((scaled_font->surface_backend != NULL &&
- scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
- (font_private != NULL && font_private->display != dst->display))
+ if (! _cairo_xlib_surface_owns_font (dst, scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
- * them. We tie into the scaled_font's glyph cache and remove
- * glyphs from the X server when they are ejected from the
- * scaled_font cache. Because of this we first freeze the
- * scaled_font's cache so that we don't cause any of our glyphs to
- * be ejected and removed from the X server before we have a
- * chance to render them. */
- _cairo_scaled_font_freeze_cache (scaled_font);
+ * them.
+ */
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
* the mask (the glyphs). This code below was executed as a side effect
@@ -4053,14 +4060,19 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (status)
goto BAIL1;
- status = _cairo_xlib_surface_emit_glyphs (dst,
- (cairo_xlib_glyph_t *) glyphs,
- num_glyphs,
- scaled_font,
- op,
- src,
- &attributes,
- remaining_glyphs);
+ _cairo_scaled_font_freeze_cache (scaled_font);
+ if (_cairo_xlib_surface_owns_font (dst, scaled_font)) {
+ status = _cairo_xlib_surface_emit_glyphs (dst,
+ (cairo_xlib_glyph_t *) glyphs,
+ num_glyphs,
+ scaled_font,
+ op,
+ src,
+ &attributes,
+ remaining_glyphs);
+ } else
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_scaled_font_thaw_cache (scaled_font);
BAIL1:
if (src)
@@ -4068,7 +4080,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (src_pattern == &solid_pattern.base)
_cairo_pattern_fini (&solid_pattern.base);
BAIL0:
- _cairo_scaled_font_thaw_cache (scaled_font);
_cairo_xlib_display_notify (dst->display);
return status;
diff --git a/src/cairoint.h b/src/cairoint.h
index cdf28b44..577c032e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1559,6 +1559,10 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
cairo_private void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
+/* This should only be called on an error path by a scaled_font constructor */
+cairo_private void
+_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
+
cairo_private cairo_status_t
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents);
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 9554c53c..6038430c 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -277,29 +277,14 @@ _test_meta_surface_show_text_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font)
{
test_meta_surface_t *surface = abstract_surface;
- cairo_int_status_t status;
surface->image_reflects_meta = FALSE;
- /* Since this is a "wrapping" surface, we're calling back into
- * _cairo_surface_show_text_glyphs from within a call to the same.
- * Since _cairo_surface_show_text_glyphs acquires a mutex, we release
- * and re-acquire the mutex around this nested call.
- *
- * Yes, this is ugly, but we consider it pragmatic as compared to
- * adding locking code to all 18 surface-backend-specific
- * show_glyphs functions, (which would get less testing and likely
- * lead to bugs).
- */
- CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
- status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
- utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters, cluster_flags,
- scaled_font);
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
-
- return status;
+ return _cairo_surface_show_text_glyphs (surface->meta, op, source,
+ utf8, utf8_len,
+ glyphs, num_glyphs,
+ clusters, num_clusters, cluster_flags,
+ scaled_font);
}
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index fb7e2e48..354f95d1 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -256,30 +256,15 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font)
{
test_paginated_surface_t *surface = abstract_surface;
- cairo_int_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
- /* Since this is a "wrapping" surface, we're calling back into
- * _cairo_surface_show_text_glyphs from within a call to the same.
- * Since _cairo_surface_show_text_glyphs acquires a mutex, we release
- * and re-acquire the mutex around this nested call.
- *
- * Yes, this is ugly, but we consider it pragmatic as compared to
- * adding locking code to all 18 surface-backend-specific
- * show_glyphs functions, (which would get less testing and likely
- * lead to bugs).
- */
- CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
- status = _cairo_surface_show_text_glyphs (surface->target, op, source,
- utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters, cluster_flags,
- scaled_font);
- CAIRO_MUTEX_LOCK (scaled_font->mutex);
-
- return status;
+ return _cairo_surface_show_text_glyphs (surface->target, op, source,
+ utf8, utf8_len,
+ glyphs, num_glyphs,
+ clusters, num_clusters, cluster_flags,
+ scaled_font);
}