[PATCH] global glyph cache
Chris Wilson
chris at chris-wilson.co.uk
Fri Nov 21 07:04:47 PST 2008
---
boilerplate/cairo-boilerplate.c | 5 +-
src/cairo-cache-private.h | 4 +
src/cairo-cache.c | 22 ++--
src/cairo-mutex-list-private.h | 1 +
src/cairo-scaled-font-private.h | 5 +-
src/cairo-scaled-font.c | 314 ++++++++++++++++++++++++++++-----------
src/cairoint.h | 9 +-
7 files changed, 253 insertions(+), 107 deletions(-)
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index f6f68f9..65b8aa9 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -866,10 +866,7 @@ void
cairo_boilerplate_scaled_font_set_max_glyphs_cached (cairo_scaled_font_t *scaled_font,
int max_glyphs)
{
- if (cairo_scaled_font_status (scaled_font))
- return;
-
- scaled_font->glyphs->max_size = max_glyphs;
+ /* XXX CAIRO_DEBUG */
}
#if HAS_DAEMON
diff --git a/src/cairo-cache-private.h b/src/cairo-cache-private.h
index 5ac8cc8..0936c3f 100644
--- a/src/cairo-cache-private.h
+++ b/src/cairo-cache-private.h
@@ -118,6 +118,10 @@ _cairo_cache_insert (cairo_cache_t *cache,
cairo_cache_entry_t *entry);
cairo_private void
+_cairo_cache_remove (cairo_cache_t *cache,
+ cairo_cache_entry_t *entry);
+
+cairo_private void
_cairo_cache_foreach (cairo_cache_t *cache,
cairo_cache_callback_func_t cache_callback,
void *closure);
diff --git a/src/cairo-cache.c b/src/cairo-cache.c
index 07c8b71..c5412e4 100644
--- a/src/cairo-cache.c
+++ b/src/cairo-cache.c
@@ -39,10 +39,6 @@
#include "cairoint.h"
static void
-_cairo_cache_remove (cairo_cache_t *cache,
- cairo_cache_entry_t *entry);
-
-static void
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional);
@@ -225,6 +221,12 @@ _cairo_cache_lookup (cairo_cache_t *cache,
(cairo_hash_entry_t *) key);
}
+static cairo_bool_t
+_cairo_cache_entry_is_non_zero (const void *entry)
+{
+ return ((cairo_cache_entry_t *)entry)->size;
+}
+
/**
* _cairo_cache_remove_random:
* @cache: a cache
@@ -239,7 +241,8 @@ _cairo_cache_remove_random (cairo_cache_t *cache)
{
cairo_cache_entry_t *entry;
- entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
+ entry = _cairo_hash_table_random_entry (cache->hash_table,
+ _cairo_cache_entry_is_non_zero);
if (unlikely (entry == NULL))
return FALSE;
@@ -307,13 +310,8 @@ _cairo_cache_insert (cairo_cache_t *cache,
* @entry: an entry that exists in the cache
*
* Remove an existing entry from the cache.
- *
- * (Note: If any caller wanted access to a non-static version of this
- * function, an improved version would require only a key rather than
- * an entry. Fixing that would require fixing _cairo_hash_table_remove
- * to return (a copy of?) the entry being removed.)
**/
-static void
+void
_cairo_cache_remove (cairo_cache_t *cache,
cairo_cache_entry_t *entry)
{
@@ -336,7 +334,7 @@ _cairo_cache_remove (cairo_cache_t *cache,
* non-specified order.
**/
void
-_cairo_cache_foreach (cairo_cache_t *cache,
+_cairo_cache_foreach (cairo_cache_t *cache,
cairo_cache_callback_func_t cache_callback,
void *closure)
{
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index f5f654d..1f66bf8 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -42,6 +42,7 @@ CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex)
CAIRO_MUTEX_DECLARE (_cairo_intern_string_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
+CAIRO_MUTEX_DECLARE (_cairo_scaled_glyph_page_cache_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
#if CAIRO_HAS_FT_FONT
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 86a50bb..412f66c 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -44,6 +44,8 @@
#include "cairo-mutex-type-private.h"
#include "cairo-reference-count-private.h"
+typedef struct _cairo_scaled_glyph_page cairo_scaled_glyph_page_t;
+
struct _cairo_scaled_font {
/* For most cairo objects, the rule for multiple threads is that
* the user is responsible for any locking if the same object is
@@ -75,7 +77,6 @@ struct _cairo_scaled_font {
* scaled_font->mutex in the generic scaled_font code.
*/
- /* must be first to be stored in a hash table */
cairo_hash_entry_t hash_entry;
/* useful bits for _cairo_scaled_font_nil */
@@ -103,7 +104,7 @@ struct _cairo_scaled_font {
/* The mutex protects modification to all subsequent fields. */
cairo_mutex_t mutex;
- cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */
+ cairo_scaled_glyph_page_t *mru_page;
/*
* One surface backend may store data in each glyph.
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ca86f51..031dedb 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -35,11 +35,28 @@
* Graydon Hoare <graydon at redhat.com>
* Owen Taylor <otaylor at redhat.com>
* Behdad Esfahbod <behdad at behdad.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-scaled-font-private.h"
+#define CAIRO_SCALED_GLYPH_PAGE_SHIFT 7
+#define CAIRO_SCALED_GLYPH_PAGE_SIZE (1 << CAIRO_SCALED_GLYPH_PAGE_SHIFT)
+#define CAIRO_SCALED_GLYPH_PAGE_INDEX(I) \
+ ((I) & (CAIRO_SCALED_GLYPH_PAGE_SIZE - 1))
+#define CAIRO_SCALED_GLYPH_PAGE_HAS_INDEX(P, I) \
+ ((I) - (P)->key.cache_entry.hash < CAIRO_SCALED_GLYPH_PAGE_SIZE)
+typedef struct _cairo_scaled_glyph_page_key {
+ cairo_cache_entry_t cache_entry;
+ cairo_scaled_font_t *scaled_font;
+} cairo_scaled_glyph_page_key_t;
+
+struct _cairo_scaled_glyph_page {
+ cairo_scaled_glyph_page_key_t key;
+ cairo_scaled_glyph_t glyphs[CAIRO_SCALED_GLYPH_PAGE_SIZE];
+};
+
/*
* Notes:
*
@@ -131,16 +148,16 @@
* Now compare the scaled-glyph space to device-space and surface-space
* and convince yourself that:
*
- * (x_bearing,y_bearing) = (-x,-y) = - device_offset
+ * (x_bearing,y_bearing) = (-x,-y) = - device_offset
*
* That's right. If you are not convinced yet, contrast the definition
* of the two:
*
- * "(x_bearing,y_bearing) is the coordinates of top-left of the
- * glyph relative to the glyph origin."
+ * "(x_bearing,y_bearing) is the coordinates of top-left of the
+ * glyph relative to the glyph origin."
*
- * "In other words: device_offset is the coordinates of the
- * device-space origin relative to the top-left of the surface."
+ * "In other words: device_offset is the coordinates of the
+ * device-space origin relative to the top-left of the surface."
*
* and note that glyph origin = device-space origin.
*/
@@ -148,15 +165,9 @@
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)
-{
- const cairo_scaled_glyph_t *key_a = abstract_key_a;
- const cairo_scaled_glyph_t *key_b = abstract_key_b;
-
- return (_cairo_scaled_glyph_index (key_a) ==
- _cairo_scaled_glyph_index (key_b));
-}
+static void
+_cairo_scaled_glyph_page_cache_remove_scaled_font (cairo_scaled_font_t
+ *scaled_font);
static void
_cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
@@ -166,20 +177,17 @@ _cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL)
surface_backend->scaled_glyph_fini (scaled_glyph, scaled_font);
+
if (scaled_glyph->surface != NULL)
cairo_surface_destroy (&scaled_glyph->surface->base);
+
if (scaled_glyph->path != NULL)
_cairo_path_fixed_destroy (scaled_glyph->path);
+
if (scaled_glyph->meta_surface != NULL)
cairo_surface_destroy (scaled_glyph->meta_surface);
-}
-static void
-_cairo_scaled_glyph_destroy (void *abstract_glyph)
-{
- cairo_scaled_glyph_t *scaled_glyph = abstract_glyph;
- _cairo_scaled_glyph_fini (scaled_glyph);
- free (scaled_glyph);
+ scaled_glyph->scaled_font = NULL;
}
#define ZOMBIE 0
@@ -203,7 +211,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
{ 0., 0., 0., 0., 0. }, /* extents */
{ 0., 0., 0., 0., 0. }, /* fs_extents */
CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
- NULL, /* glyphs */
+ NULL, /* mru_page */
NULL, /* surface_backend */
NULL, /* surface_private */
CAIRO_SCALED_FONT_BACKEND_DEFAULT,
@@ -309,7 +317,7 @@ typedef struct _cairo_scaled_font_map {
int num_holdovers;
} cairo_scaled_font_map_t;
-static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
+static cairo_scaled_font_map_t *cairo_scaled_font_map;
static int
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
@@ -399,6 +407,150 @@ _cairo_scaled_font_map_destroy (void)
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
+/* Global Glyph Cache
+ *
+ * We maintain a global pool of glyphs split between all open fonts. This
+ * allows a heavily used individual font to cache more glyphs than we could
+ * manage if we used per-font glyph caches, but at the same time maintains
+ * fairness across all fonts and provides a cap on the maximum number of
+ * global glyphs.
+ *
+ * The glyphs are allocated in pages, which are cached in the global pool.
+ * Using pages means we can exploit spatial locality within the font (nearby
+ * indices are typically used in clusters) and allow the scaled font to
+ * reserve a single MRU page of glyphs.
+ */
+
+/* XXX: This number is arbitrary---we've never done any measurement of this. */
+#define MAX_GLYPH_PAGES_CACHED 512
+
+static cairo_cache_t *cairo_scaled_glyph_page_cache;
+
+static cairo_bool_t
+_cairo_scaled_glyph_pages_equal (const void *key_a, const void *key_b)
+{
+ const cairo_scaled_glyph_page_key_t *a = key_a;
+ const cairo_scaled_glyph_page_key_t *b = key_b;
+
+ return
+ a->cache_entry.hash == b->cache_entry.hash &&
+ a->scaled_font == b->scaled_font;
+}
+
+static void
+_cairo_scaled_glyph_page_destroy (void *closure)
+{
+ cairo_scaled_glyph_page_t *page = closure;
+ int n;
+
+ for (n = 0; n < CAIRO_SCALED_GLYPH_PAGE_SIZE; n++) {
+ if (page->glyphs[n].scaled_font != NULL)
+ _cairo_scaled_glyph_fini (&page->glyphs[n]);
+ }
+
+ free (page);
+}
+
+static void
+_cairo_scaled_glyph_page_cache_freeze (void)
+{
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+
+ if (cairo_scaled_glyph_page_cache == NULL) {
+ cairo_scaled_glyph_page_cache =
+ _cairo_cache_create (_cairo_scaled_glyph_pages_equal,
+ _cairo_scaled_glyph_page_destroy,
+ MAX_GLYPH_PAGES_CACHED);
+ }
+
+ _cairo_cache_freeze (cairo_scaled_glyph_page_cache);
+
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+}
+
+static cairo_scaled_glyph_page_t *
+_cairo_scaled_glyph_page_cache_lookup (cairo_scaled_font_t *scaled_font,
+ unsigned long index)
+{
+ cairo_scaled_glyph_page_key_t key;
+ cairo_scaled_glyph_page_t *page;
+ cairo_status_t status;
+
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+
+ assert (cairo_scaled_glyph_page_cache != NULL);
+ assert (cairo_scaled_glyph_page_cache->freeze_count > 0);
+
+ key.cache_entry.hash =
+ (index >> CAIRO_SCALED_GLYPH_PAGE_SHIFT) ^
+ (unsigned long) scaled_font;
+ key.scaled_font = scaled_font;
+
+ page = _cairo_cache_lookup (cairo_scaled_glyph_page_cache,
+ &key.cache_entry);
+ if (page == NULL) {
+ /*
+ * On miss, create glyph page and insert into cache
+ */
+ page = malloc (sizeof (cairo_scaled_glyph_page_t));
+ if (unlikely (page == NULL))
+ goto UNLOCK;
+
+ page->key.cache_entry.hash = key.cache_entry.hash;
+ /* We currently don't differentiate on glyph size at all */
+ page->key.cache_entry.size = 1;
+ page->key.scaled_font = scaled_font;
+
+ status = _cairo_cache_insert (cairo_scaled_glyph_page_cache,
+ &page->key.cache_entry);
+ if (unlikely (status)) {
+ free (page);
+ page = NULL;
+ goto UNLOCK;
+ }
+
+ memset (page->glyphs, 0, sizeof (page->glyphs));
+ }
+
+ UNLOCK:
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+
+ return page;
+}
+
+static void
+_cairo_scaled_glyph_page_cache_remove_scaled_font_cb (void *entry,
+ void *closure)
+{
+ cairo_scaled_glyph_page_key_t *key = entry;
+
+ if (key->scaled_font == closure && key->cache_entry.size)
+ _cairo_cache_remove (cairo_scaled_glyph_page_cache, entry);
+}
+
+static void
+_cairo_scaled_glyph_page_cache_remove_scaled_font (cairo_scaled_font_t *scaled_font)
+{
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+
+ if (cairo_scaled_glyph_page_cache != NULL) {
+ _cairo_cache_foreach (cairo_scaled_glyph_page_cache,
+ _cairo_scaled_glyph_page_cache_remove_scaled_font_cb,
+ scaled_font);
+ }
+
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+}
+
+static void
+_cairo_scaled_glyph_page_cache_thaw (void)
+{
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+
+ _cairo_cache_thaw (cairo_scaled_glyph_page_cache);
+
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+}
/* If a scaled font wants to unlock the font map while still being
* created (needed for user-fonts), we need to take extra care not
@@ -577,13 +729,6 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
cairo_font_options_equal (&key_a->options, &key_b->options));
}
-/* XXX: This 256 number is arbitrary---we've never done any measurement
- * of this. In fact, having a per-font glyph caches each managed
- * separately is probably not what we want anyway. Would probably be
- * much better to have a single cache for glyphs with random
- * replacement across all glyphs of all fonts. */
-#define MAX_GLYPHS_CACHED_PER_FONT 256
-
/*
* Basic #cairo_scaled_font_t object management
*/
@@ -635,12 +780,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
scaled_font->finished = FALSE;
- scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
- _cairo_scaled_glyph_destroy,
- MAX_GLYPHS_CACHED_PER_FONT);
- if (unlikely (scaled_font->glyphs == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
_cairo_user_data_array_init (&scaled_font->user_data);
@@ -649,6 +788,8 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
CAIRO_MUTEX_INIT (scaled_font->mutex);
+ scaled_font->mru_page = NULL;
+
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
@@ -664,13 +805,13 @@ _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
- _cairo_cache_freeze (scaled_font->glyphs);
+ _cairo_scaled_glyph_page_cache_freeze ();
}
void
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
{
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_glyph_page_cache_thaw ();
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
}
@@ -679,10 +820,13 @@ _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
{
assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
- _cairo_cache_destroy (scaled_font->glyphs);
- scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
- _cairo_scaled_glyph_destroy,
- MAX_GLYPHS_CACHED_PER_FONT);
+ if (scaled_font->mru_page != NULL) {
+ cairo_scaled_glyph_page_cache->size++;
+ scaled_font->mru_page->key.cache_entry.size = 1;
+ scaled_font->mru_page = NULL;
+ }
+
+ _cairo_scaled_glyph_page_cache_remove_scaled_font (scaled_font);
}
cairo_status_t
@@ -719,12 +863,17 @@ _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
{
scaled_font->finished = TRUE;
+ if (scaled_font->mru_page != NULL) {
+ cairo_scaled_glyph_page_cache->size++;
+ scaled_font->mru_page->key.cache_entry.size = 1;
+ scaled_font->mru_page = NULL;
+ }
+
+ _cairo_scaled_glyph_page_cache_remove_scaled_font (scaled_font);
+
if (scaled_font->font_face != NULL)
cairo_font_face_destroy (scaled_font->font_face);
- if (scaled_font->glyphs != NULL)
- _cairo_cache_destroy (scaled_font->glyphs);
-
CAIRO_MUTEX_FINI (scaled_font->mutex);
if (scaled_font->surface_backend != NULL &&
@@ -968,6 +1117,13 @@ _cairo_scaled_font_reset_static_data (void)
}
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
+
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+ if (cairo_scaled_glyph_page_cache != NULL) {
+ _cairo_cache_destroy (cairo_scaled_glyph_page_cache);
+ cairo_scaled_glyph_page_cache = NULL;
+ }
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
/**
@@ -1025,9 +1181,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
assert (font_map != NULL);
if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
-
-
- if (!scaled_font->placeholder && scaled_font->hash_entry.hash != ZOMBIE) {
+ if (! scaled_font->placeholder &&
+ scaled_font->hash_entry.hash != ZOMBIE)
+ {
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon (and is why we must hold the lock over the atomic op on
@@ -1053,7 +1209,6 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
font_map->num_holdovers++;
} else
lru = scaled_font;
-
}
_cairo_scaled_font_map_unlock ();
@@ -1145,13 +1300,6 @@ 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. */
/**
@@ -2340,58 +2488,52 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_t **scaled_glyph_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_cache_entry_t key;
+ cairo_scaled_glyph_page_t *page;
cairo_scaled_glyph_t *scaled_glyph;
cairo_scaled_glyph_info_t need_info;
if (scaled_font->status)
return scaled_font->status;
- assert (_cairo_scaled_font_is_frozen (scaled_font));
+ page = scaled_font->mru_page;
+ if (page != NULL && ! CAIRO_SCALED_GLYPH_PAGE_HAS_INDEX (page, index)) {
+ cairo_scaled_glyph_page_cache->size++;
+ page->key.cache_entry.size = 1;
+ scaled_font->mru_page = NULL;
+ page = NULL;
+ }
+
+ if (page == NULL) {
+ page = _cairo_scaled_glyph_page_cache_lookup (scaled_font, index);
+ if (page == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ scaled_font->mru_page = page;
+ page->key.cache_entry.size = 0;
+ cairo_scaled_glyph_page_cache->size--;
- key.hash = index;
/*
* Check cache for glyph
*/
info |= CAIRO_SCALED_GLYPH_INFO_METRICS;
- scaled_glyph = _cairo_cache_lookup (scaled_font->glyphs, &key);
- if (scaled_glyph == NULL) {
- /*
- * On miss, create glyph and insert into cache
- */
- scaled_glyph = malloc (sizeof (cairo_scaled_glyph_t));
- if (unlikely (scaled_glyph == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- _cairo_scaled_glyph_set_index(scaled_glyph, index);
- scaled_glyph->cache_entry.size = 1; /* We currently don't differentiate on glyph size at all */
+ scaled_glyph = &page->glyphs[CAIRO_SCALED_GLYPH_PAGE_INDEX (index)];
+ if (scaled_glyph->scaled_font == NULL) {
+ scaled_glyph->index = index;
scaled_glyph->scaled_font = scaled_font;
- scaled_glyph->surface = NULL;
- scaled_glyph->path = NULL;
- scaled_glyph->meta_surface = NULL;
- scaled_glyph->surface_private = NULL;
/* ask backend to initialize metrics and shape fields */
status = (*scaled_font->backend->
scaled_glyph_init) (scaled_font, scaled_glyph, info);
if (unlikely (status)) {
- _cairo_scaled_glyph_destroy (scaled_glyph);
- goto CLEANUP;
- }
-
- /* on success, the cache takes ownership of the scaled_glyph */
- status = _cairo_cache_insert (scaled_font->glyphs,
- &scaled_glyph->cache_entry);
- if (unlikely (status)) {
- _cairo_scaled_glyph_destroy (scaled_glyph);
+ _cairo_scaled_glyph_fini (scaled_glyph);
goto CLEANUP;
}
}
+
/*
* Check and see if the glyph, as provided,
- * already has the requested data and ammend it if not
+ * already has the requested data and amend it if not
*/
need_info = 0;
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
diff --git a/src/cairoint.h b/src/cairoint.h
index 24ce6b4..aff3343 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -343,21 +343,24 @@ typedef struct _cairo_unscaled_font {
} cairo_unscaled_font_t;
typedef struct _cairo_scaled_glyph {
- cairo_cache_entry_t cache_entry; /* hash is glyph index */
+ unsigned long index;
cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
+
cairo_text_extents_t metrics; /* user-space metrics */
cairo_text_extents_t fs_metrics; /* font-space metrics */
cairo_box_t bbox; /* device-space bounds */
int16_t x_advance; /* device-space rounded X advance */
int16_t y_advance; /* device-space rounded Y advance */
+
cairo_image_surface_t *surface; /* device-space image */
cairo_path_fixed_t *path; /* device-space outline */
cairo_surface_t *meta_surface; /* device-space meta-surface */
+
void *surface_private; /* for the surface backend */
} cairo_scaled_glyph_t;
-#define _cairo_scaled_glyph_index(g) ((g)->cache_entry.hash)
-#define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i))
+#define _cairo_scaled_glyph_index(g) ((g)->index)
+#define _cairo_scaled_glyph_set_index(g, i) ((g)->index = (i))
#include "cairo-scaled-font-private.h"
--
1.6.0.4
--=-eNDd1Q3hiD2gO39lYJIr--
More information about the cairo
mailing list