[cairo-commit] cairo/src Makefile.am, 1.64,
1.65 cairo-cache-private.h, NONE, 1.1 cairo-cache.c, 1.14,
1.15 cairo-debug.c, 1.1, 1.2 cairo-font.c, 1.76,
1.77 cairo-ft-font.c, 1.110, 1.111 cairo-gstate.c, 1.168,
1.169 cairo-path.c, 1.27, 1.28 cairo-scaled-font.c, NONE,
1.1 cairo-xlib-surface.c, 1.118, 1.119 cairoint.h, 1.207, 1.208
Keith Packard
commit at pdx.freedesktop.org
Wed Aug 31 15:08:05 PDT 2005
- Previous message: [cairo-commit] cairo ChangeLog,1.1027,1.1028
- Next message: [cairo-commit] cairo/test clip-operator-ref.png, 1.4,
1.5 operator-clear-ref.png, 1.2, 1.3 operator-source-ref.png,
1.2, 1.3 text-antialias-gray-ref.png, 1.2,
1.3 text-antialias-gray.c, 1.2,
1.3 text-antialias-none-ref.png, 1.2,
1.3 text-antialias-none.c, 1.3,
1.4 text-antialias-subpixel-ref.png, 1.3,
1.4 text-antialias-subpixel.c, 1.3,
1.4 unbounded-operator-ref.png, 1.3, 1.4
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: keithp
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv6824/src
Modified Files:
Makefile.am cairo-cache.c cairo-debug.c cairo-font.c
cairo-ft-font.c cairo-gstate.c cairo-path.c
cairo-xlib-surface.c cairoint.h
Added Files:
cairo-cache-private.h cairo-scaled-font.c
Log Message:
2005-08-31 Keith Packard <keithp at keithp.com>
Reviewed by: otaylor, cworth
* src/Makefile.am:
Split out scaled font code to cairo-scaled-font.c
* src/cairo-cache-private.h:
* src/cairo-cache.c: (_cairo_cache_init), (_cairo_cache_fini),
(_cairo_cache_create), (_cairo_cache_destroy),
(_cairo_cache_preserve), (_cairo_cache_release),
(_cairo_cache_lookup), (_cairo_cache_remove_random),
(_cairo_cache_insert), (_cairo_cache_remove),
(_cairo_cache_foreach):
Replace cairo cache implementation (this code from cworth)
* src/cairo-debug.c: (cairo_debug_reset_static_data):
* src/cairo-font.c: (_cairo_font_reset_static_data):
No more global glyph cache to clean up
* src/cairo-ft-font.c: (_get_bitmap_surface),
(_render_glyph_outline), (_render_glyph_bitmap),
(_transform_glyph_bitmap), (_get_pattern_ft_options),
(_cairo_ft_scaled_font_create), (_cairo_ft_scaled_font_create_toy),
(_decompose_glyph_outline), (_cairo_ft_scaled_glyph_init),
(_cairo_ft_ucs4_to_index), (_cairo_ft_show_glyphs),
(_cairo_ft_font_face_scaled_font_create),
(_cairo_ft_font_face_create),
(cairo_ft_font_face_create_for_pattern),
(cairo_ft_font_face_create_for_ft_face):
Store glyphs in new per-scaled font caches which
hold user-space metrics and device space bounding boxes
* src/cairo-gstate.c: (_cairo_gstate_text_to_glyphs),
(_cairo_gstate_show_glyphs_draw_func), (_cairo_gstate_show_glyphs):
Refactor glyph drawing APIs so that the surface API is
invoked directly from the gstate code.
* src/cairo-path.c: (_cairo_path_fixed_create),
(_cairo_path_fixed_destroy):
Add path creation/destruction routines (to hold glyph paths)
* src/cairo-scaled-font.c: (_cairo_scaled_glyph_keys_equal),
(_cairo_scaled_glyph_fini), (_cairo_scaled_glyph_destroy),
(_cairo_scaled_font_set_error), (cairo_scaled_font_status),
(_cairo_scaled_font_map_lock), (_cairo_scaled_font_map_unlock),
(_cairo_scaled_font_map_destroy), (_hash_bytes_fnv),
(_cairo_scaled_font_init_key), (_cairo_scaled_font_keys_equal),
(_cairo_scaled_font_init), (_cairo_scaled_font_set_metrics),
(_cairo_scaled_font_fini), (cairo_scaled_font_create),
(cairo_scaled_font_reference), (cairo_scaled_font_destroy),
(cairo_scaled_font_extents), (cairo_scaled_font_glyph_extents),
(_cairo_scaled_font_text_to_glyphs),
(_cairo_scaled_font_glyph_device_extents),
(_cairo_scaled_font_show_glyphs), (_scaled_glyph_path_move_to),
(_scaled_glyph_path_line_to), (_scaled_glyph_path_curve_to),
(_scaled_glyph_path_close_path), (_cairo_scaled_font_glyph_path),
(_cairo_scaled_glyph_set_metrics),
(_cairo_scaled_glyph_set_surface), (_cairo_scaled_glyph_set_path),
(_cairo_scaled_glyph_lookup):
New implementation of scaled fonts which uses per-scaled_font
caches for glyphs and keeps user-space metrics, device-space bboxes
along with glyph images and/or glyph paths.
* src/cairo-xlib-surface.c:
(_cairo_xlib_surface_create_similar_with_format),
(_cairo_xlib_surface_create_similar), (_cairo_xlib_surface_finish),
(_cairo_xlib_surface_clone_similar),
(_cairo_xlib_surface_font_init),
(_cairo_xlib_surface_scaled_font_fini),
(_cairo_xlib_surface_scaled_glyph_fini),
(_cairo_xlib_surface_add_glyph),
(_cairo_xlib_surface_show_glyphs8),
(_cairo_xlib_surface_show_glyphs16),
(_cairo_xlib_surface_show_glyphs32),
(_cairo_xlib_surface_show_glyphs):
Adapt to new scaled font API changes.
* src/cairoint.h:
New cache and scaled_font APIs
* test/clip-operator-ref.png:
* test/operator-clear-ref.png:
* test/operator-source-ref.png:
* test/text-antialias-gray-ref.png:
* test/text-antialias-gray.c:
* test/text-antialias-none-ref.png:
* test/text-antialias-none.c:
* test/text-antialias-subpixel-ref.png:
* test/text-antialias-subpixel.c:
* test/unbounded-operator-ref.png:
Repond to bug fix in metrics computation for glyphs
where y values were rounded up instead of down
because of a sign difference between cairo and FreeType.
Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- Makefile.am 24 Aug 2005 14:56:46 -0000 1.64
+++ Makefile.am 31 Aug 2005 22:08:02 -0000 1.65
@@ -121,6 +121,7 @@
cairo-pen.c \
cairo-polygon.c \
cairo-region.c \
+ cairo-scaled-font.c \
cairo-slope.c \
cairo-spline.c \
cairo-surface.c \
--- NEW FILE: cairo-cache-private.h ---
(This appears to be a binary file; contents omitted.)
Index: cairo-cache.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-cache.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cairo-cache.c 17 Aug 2005 16:51:09 -0000 1.14
+++ cairo-cache.c 31 Aug 2005 22:08:02 -0000 1.15
@@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
- * This file is Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -30,481 +31,298 @@
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
- * Keith Packard
+ * Keith Packard <keithp at keithp.com>
* Graydon Hoare <graydon at redhat.com>
+ * Carl Worth <cworth at cworth.org>
*/
#include "cairoint.h"
-/*
- * This structure, and accompanying table, is borrowed/modified from the
- * file xserver/render/glyph.c in the freedesktop.org x server, with
- * permission (and suggested modification of doubling sizes) by Keith
- * Packard.
- */
+struct _cairo_cache {
+ cairo_hash_table_t *hash_table;
-static const cairo_cache_arrangement_t cache_arrangements [] = {
- { 16, 43, 41 },
- { 32, 73, 71 },
- { 64, 151, 149 },
- { 128, 283, 281 },
- { 256, 571, 569 },
- { 512, 1153, 1151 },
- { 1024, 2269, 2267 },
- { 2048, 4519, 4517 },
- { 4096, 9013, 9011 },
- { 8192, 18043, 18041 },
- { 16384, 36109, 36107 },
- { 32768, 72091, 72089 },
- { 65536, 144409, 144407 },
- { 131072, 288361, 288359 },
- { 262144, 576883, 576881 },
- { 524288, 1153459, 1153457 },
- { 1048576, 2307163, 2307161 },
- { 2097152, 4613893, 4613891 },
- { 4194304, 9227641, 9227639 },
- { 8388608, 18455029, 18455027 },
- { 16777216, 36911011, 36911009 },
- { 33554432, 73819861, 73819859 },
- { 67108864, 147639589, 147639587 },
- { 134217728, 295279081, 295279079 },
- { 268435456, 590559793, 590559791 }
+ cairo_destroy_func_t entry_destroy;
+
+ unsigned long max_size;
+ unsigned long size;
+
+ cairo_bool_t preserve_entries;
};
-#define N_CACHE_SIZES (sizeof(cache_arrangements)/sizeof(cache_arrangements[0]))
+static cairo_status_t
+_cairo_cache_init (cairo_cache_t *cache,
+ cairo_cache_keys_equal_func_t keys_equal,
+ cairo_destroy_func_t entry_destroy,
+ unsigned long max_size)
+{
+ cache->hash_table = _cairo_hash_table_create (keys_equal);
+ if (cache->hash_table == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
-/*
- * Entries 'e' are poiners, in one of 3 states:
- *
- * e == NULL: The entry has never had anything put in it
- * e != DEAD_ENTRY: The entry has an active value in it currently
- * e == DEAD_ENTRY: The entry *had* a value in it at some point, but the
- * entry has been killed. Lookups requesting free space can
- * reuse these entries; lookups requesting a precise match
- * should neither return these entries nor stop searching when
- * seeing these entries.
- *
- * We expect keys will not be destroyed frequently, so our table does not
- * contain any explicit shrinking code nor any chain-coalescing code for
- * entries randomly deleted by memory pressure (except during rehashing, of
- * course). These assumptions are potentially bad, but they make the
- * implementation straightforward.
- *
- * Revisit later if evidence appears that we're using excessive memory from
- * a mostly-dead table.
- *
- * Generally you do not need to worry about freeing cache entries; the
- * cache will expire entries randomly as it experiences memory pressure.
- * If max_memory is set, entries are not expired, and must be explicitely
- * removed.
- *
- * This table is open-addressed with double hashing. Each table size is a
- * prime chosen to be a little more than double the high water mark for a
- * given arrangement, so the tables should remain < 50% full. The table
- * size makes for the "first" hash modulus; a second prime (2 less than the
- * first prime) serves as the "second" hash modulus, which is co-prime and
- * thus guarantees a complete permutation of table indices.
- *
- */
+ cache->entry_destroy = entry_destroy;
-#define DEAD_ENTRY ((cairo_cache_entry_base_t *) 1)
-#define NULL_ENTRY_P(cache, i) ((cache)->entries[i] == NULL)
-#define DEAD_ENTRY_P(cache, i) ((cache)->entries[i] == DEAD_ENTRY)
-#define LIVE_ENTRY_P(cache, i) \
- (!((NULL_ENTRY_P((cache),(i))) || (DEAD_ENTRY_P((cache),(i)))))
+ cache->max_size = max_size;
+ cache->size = 0;
-#ifdef NDEBUG
-#define _cache_sane_state(c)
-#else
-static void
-_cache_sane_state (cairo_cache_t *cache)
-{
- assert (cache != NULL);
- assert (cache->entries != NULL);
- assert (cache->backend != NULL);
- assert (cache->arrangement != NULL);
- /* Cannot check this, a single object may larger */
- /* assert (cache->used_memory <= cache->max_memory); */
- assert (cache->live_entries <= cache->arrangement->size);
+ cache->preserve_entries = FALSE;
+
+ return CAIRO_STATUS_SUCCESS;
}
-#endif
static void
-_entry_destroy (cairo_cache_t *cache, unsigned long i)
+_cairo_cache_fini (cairo_cache_t *cache)
{
- _cache_sane_state (cache);
+ cairo_cache_entry_t *entry;
- if (LIVE_ENTRY_P(cache, i))
- {
- cairo_cache_entry_base_t *entry = cache->entries[i];
- assert(cache->live_entries > 0);
- assert(cache->used_memory >= entry->memory);
+ /* We have to manually remove all entries from the cache ourselves
+ * rather than relying on _cairo_hash_table_destroy to do that
+ * since otherwise the cache->entry_destroy callback would not get
+ * called on each entry. */
- cache->live_entries--;
- cache->used_memory -= entry->memory;
- cache->backend->destroy_entry (cache, entry);
- cache->entries[i] = DEAD_ENTRY;
+ while (1) {
+ entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
+ if (entry == NULL)
+ break;
+ _cairo_cache_remove (cache, entry);
}
-}
-
-static cairo_cache_entry_base_t **
-_cache_lookup (cairo_cache_t *cache,
- void *key,
- int (*predicate)(void*,void*,void*))
-{
-
- cairo_cache_entry_base_t **probe;
- unsigned long hash;
- unsigned long table_size, i, idx, step;
-
- _cache_sane_state (cache);
- assert (key != NULL);
-
- table_size = cache->arrangement->size;
- hash = cache->backend->hash (cache, key);
- idx = hash % table_size;
- step = 0;
-
- for (i = 0; i < table_size; ++i)
- {
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- cache->probes++;
-#endif
- assert(idx < table_size);
- probe = cache->entries + idx;
- /*
- * There are two lookup modes: searching for a free slot and searching
- * for an exact entry.
- */
+ _cairo_hash_table_destroy (cache->hash_table);
+ cache->size = 0;
+}
- if (predicate != NULL)
- {
- /* We are looking up an exact entry. */
- if (*probe == NULL)
- {
- /* Found an empty spot, there can't be a match */
- break;
- }
- else if (*probe != DEAD_ENTRY
- && (*probe)->hashcode == hash
- && predicate (cache, key, *probe))
- {
- return probe;
- }
- }
- else
- {
- /* We are just looking for a free slot. */
- if (*probe == NULL
- || *probe == DEAD_ENTRY)
- {
- return probe;
- }
- }
+/**
+ * _cairo_cache_create:
+ * @keys_equal: a function to return TRUE if two keys are equal
+ * @entry_destroy: destroy notifier for cache entries
+ * @max_size: the maximum size for this cache
+ *
+ * Creates a new cache using the keys_equal() function to determine
+ * the equality of entries.
+ *
+ * Data is provided to the cache in the form of user-derived version
+ * of cairo_cache_entry_t. A cache entry must be able to hold hash
+ * code, a size, and the key/value pair being stored in the
+ * cache. Sometimes only the key will be necessary, (as in
+ * _cairo_cache_remove()), and in these cases the value portion of the
+ * entry need not be initialized.
+ *
+ * The units for max_size can be chosen by the caller, but should be
+ * consistent with the units of the size field of cache entries. When
+ * adding an entry with _cairo_cache_insert if the total size of
+ * entries in the cache would exceed max_size then entries will be
+ * removed at random until the new entry would fit or the cache is
+ * empty. Then the new entry is inserted.
+ *
+ * There are cases in which the automatic removal of entries is
+ * undesired. If the cache entries have reference counts, then it is a
+ * simple matter to use the reference counts to ensure that entries
+ * continue to live even after being ejected from the cache. However,
+ * in some cases the memory overhead of adding a reference count to
+ * the entry would be objectionable. In such cases, the
+ * _cairo_cache_preserve() and _cairo_cache_release() calls can be
+ * used to establish a window during which no automatic removal of
+ * entries will occur.
+ *
+ * Return value:
+ **/
+cairo_cache_t *
+_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+ cairo_destroy_func_t entry_destroy,
+ unsigned long max_size)
+{
+ cairo_status_t status;
+ cairo_cache_t *cache;
- if (step == 0) {
- step = hash % cache->arrangement->rehash;
- if (step == 0)
- step = 1;
- }
+ cache = malloc (sizeof (cairo_cache_t));
+ if (cache == NULL)
+ return NULL;
- idx += step;
- if (idx >= table_size)
- idx -= table_size;
+ status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
+ if (status) {
+ free (cache);
+ return NULL;
}
- /*
- * The table should not have permitted you to get here if you were just
- * looking for a free slot: there should have been room.
- */
- assert(predicate != NULL);
- return NULL;
+ return cache;
}
-static cairo_cache_entry_base_t **
-_find_available_entry_for (cairo_cache_t *cache,
- void *key)
+/**
+ * _cairo_cache_destroy:
+ * @cache: a cache to destroy
+ *
+ * Immediately destroys the given cache, freeing all resources
+ * associated with it. As part of this process, the entry_destroy()
+ * function, (as passed to _cairo_cache_create), will be called for
+ * each entry in the cache.
+ **/
+void
+_cairo_cache_destroy (cairo_cache_t *cache)
{
- return _cache_lookup (cache, key, NULL);
-}
+ _cairo_cache_fini (cache);
-static cairo_cache_entry_base_t **
-_find_exact_live_entry_for (cairo_cache_t *cache,
- void *key)
-{
- return _cache_lookup (cache, key, cache->backend->keys_equal);
+ free (cache);
}
-static const cairo_cache_arrangement_t *
-_find_cache_arrangement (unsigned long proposed_size)
+/**
+ * _cairo_cache_preserve:
+ * @cache: a cache with some precious entries in it (or about to be
+ * added)
+ *
+ * Disable the automatic ejection of entries from the cache. Future
+ * calls to _cairo_cache_insert will add new entries to the cache
+ * regardless of how large the cache grows. See
+ * _cairo_cache_release().
+ **/
+void
+_cairo_cache_preserve (cairo_cache_t *cache)
{
- unsigned long idx;
-
- for (idx = 0; idx < N_CACHE_SIZES; ++idx)
- if (cache_arrangements[idx].high_water_mark >= proposed_size)
- return &cache_arrangements[idx];
- return NULL;
+ cache->preserve_entries = TRUE;
}
-static cairo_status_t
-_resize_cache (cairo_cache_t *cache, unsigned long proposed_size)
+/**
+ * _cairo_cache_release:
+ * @cache: a cache, just after the entries in it have become less
+ * previous
+ *
+ * Cancel the effects of _cairo_cache_preserve(). That is, allow the
+ * cache to resume ejecting entries when it is larger than max_size as
+ * passed to cairo_cache_create. If the cache is already larger than
+ * max_size, no entries will be immediately removed, but the cache
+ * will be brought down to size at the time of the next call to
+ * _cairo_cache_insert.
+ **/
+void
+_cairo_cache_release (cairo_cache_t *cache)
{
- cairo_cache_t tmp;
- cairo_cache_entry_base_t **e;
- unsigned long new_size, i;
-
- tmp = *cache;
- tmp.arrangement = _find_cache_arrangement (proposed_size);
- assert(tmp.arrangement != NULL);
- if (tmp.arrangement == cache->arrangement)
- return CAIRO_STATUS_SUCCESS;
-
- new_size = tmp.arrangement->size;
- tmp.entries = calloc (new_size, sizeof (cairo_cache_entry_base_t *));
- if (tmp.entries == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- for (i = 0; i < cache->arrangement->size; ++i) {
- if (LIVE_ENTRY_P(cache, i)) {
- e = _find_available_entry_for (&tmp, cache->entries[i]);
- assert (e != NULL);
- *e = cache->entries[i];
- }
- }
- free (cache->entries);
- cache->entries = tmp.entries;
- cache->arrangement = tmp.arrangement;
- return CAIRO_STATUS_SUCCESS;
+ cache->preserve_entries = FALSE;
}
-
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
-static double
-_load_factor (cairo_cache_t *cache)
+/**
+ * _cairo_cache_lookup:
+ * @cache: a cache
+ * @key: the key of interest
+ * @entry_return: pointer for return value
+ *
+ * Performs a lookup in @cache looking for an entry which has a key
+ * that matches @key, (as determined by the keys_equal() function
+ * passed to _cairo_cache_create).
+ *
+ * Return value: TRUE if there is an entry in the cache that matches
+ * @key, (which will now be in *entry_return). FALSE otherwise, (in
+ * which case *entry_return will be NULL).
+ **/
+cairo_private cairo_bool_t
+_cairo_cache_lookup (cairo_cache_t *cache,
+ cairo_cache_entry_t *key,
+ cairo_cache_entry_t **entry_return)
{
- return ((double) cache->live_entries)
- / ((double) cache->arrangement->size);
-}
-#endif
-
-/* Find a random in the cache matching the given predicate. We use the
- * same algorithm as the probing algorithm to walk over the entries in
- * the hash table in a pseudo-random order. Walking linearly would
- * favor entries following gaps in the hash table. We could also
- * call rand() repeatedly, which works well for almost-full tables,
- * but degrades when the table is almost empty, or predicate
- * returns false for most entries.
- */
-static cairo_cache_entry_base_t **
-_random_entry (cairo_cache_t *cache,
- int (*predicate)(void*))
-{
- cairo_cache_entry_base_t **probe;
- unsigned long hash;
- unsigned long table_size, i, idx, step;
-
- _cache_sane_state (cache);
-
- table_size = cache->arrangement->size;
- hash = rand ();
- idx = hash % table_size;
- step = 0;
-
- for (i = 0; i < table_size; ++i)
- {
- assert(idx < table_size);
- probe = cache->entries + idx;
-
- if (LIVE_ENTRY_P(cache, idx)
- && (!predicate || predicate (*probe)))
- return probe;
-
- if (step == 0) {
- step = hash % cache->arrangement->rehash;
- if (step == 0)
- step = 1;
- }
-
- idx += step;
- if (idx >= table_size)
- idx -= table_size;
- }
-
- return NULL;
+ return _cairo_hash_table_lookup (cache->hash_table,
+ (cairo_hash_entry_t *) key,
+ (cairo_hash_entry_t **) entry_return);
}
-/* public API follows */
-
-cairo_status_t
-_cairo_cache_init (cairo_cache_t *cache,
- const cairo_cache_backend_t *backend,
- unsigned long max_memory)
-{
- assert (backend != NULL);
+/**
+ * _cairo_cache_remove_random:
+ * @cache: a cache
+ *
+ * Remove a random entry from the cache.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if an entry was successfully
+ * removed. CAIRO_INT_STATUS_CACHE_EMPTY if there are no entries that
+ * can be removed.
+ **/
+static cairo_int_status_t
+_cairo_cache_remove_random (cairo_cache_t *cache)
+{
+ cairo_cache_entry_t *entry;
- if (cache != NULL){
- cache->arrangement = &cache_arrangements[0];
- cache->max_memory = max_memory;
- cache->used_memory = 0;
- cache->live_entries = 0;
+ entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
+ if (entry == NULL)
+ return CAIRO_INT_STATUS_CACHE_EMPTY;
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- cache->hits = 0;
- cache->misses = 0;
- cache->probes = 0;
-#endif
+ _cairo_cache_remove (cache, entry);
- cache->backend = backend;
- cache->entries = calloc (cache->arrangement->size,
- sizeof(cairo_cache_entry_base_t *));
-
- if (cache->entries == NULL)
- return CAIRO_STATUS_NO_MEMORY;
- }
- _cache_sane_state (cache);
return CAIRO_STATUS_SUCCESS;
}
-void
-_cairo_cache_destroy (cairo_cache_t *cache)
-{
- unsigned long i;
- if (cache == NULL)
- return;
-
- _cache_sane_state (cache);
-
- for (i = 0; i < cache->arrangement->size; ++i)
- _entry_destroy (cache, i);
-
- free (cache->entries);
- cache->entries = NULL;
- cache->backend->destroy_cache (cache);
-}
-
-void
-_cairo_cache_shrink_to (cairo_cache_t *cache,
- unsigned long max_memory)
-{
- unsigned long idx;
- /* Make some entries die if we're under memory pressure. */
- while (cache->live_entries > 0 && cache->used_memory > max_memory) {
- idx = _random_entry (cache, NULL) - cache->entries;
- assert (idx < cache->arrangement->size);
- _entry_destroy (cache, idx);
- }
-}
-
-cairo_status_t
-_cairo_cache_lookup (cairo_cache_t *cache,
- void *key,
- void **entry_return,
- int *created_entry)
+/**
+ * _cairo_cache_insert:
+ * @cache: a cache
+ * @entry: an entry to be inserted
+ *
+ * Insert @entry into the cache. If an entry exists in the cache with
+ * a matching key, then the old entry will be removed first, (and the
+ * entry_destroy() callback will be called on it).
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful or
+ * CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
+ **/
+cairo_private cairo_status_t
+_cairo_cache_insert (cairo_cache_t *cache,
+ cairo_cache_entry_t *entry)
{
+ cairo_status_t status;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_cache_entry_base_t **slot = NULL, *new_entry;
-
- _cache_sane_state (cache);
-
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- if ((cache->hits + cache->misses) % 0xffff == 0)
- printf("cache %p stats: size %ld, live %ld, load %.2f\n"
- " mem %ld/%ld, hit %ld, miss %ld\n"
- " probe %ld, %.2f probe/access\n",
- cache,
- cache->arrangement->size,
- cache->live_entries,
- _load_factor (cache),
- cache->used_memory,
- cache->max_memory,
- cache->hits,
- cache->misses,
- cache->probes,
- ((double) cache->probes)
- / ((double) (cache->hits +
- cache->misses + 1)));
-#endif
-
- /* See if we have an entry in the table already. */
- slot = _find_exact_live_entry_for (cache, key);
- if (slot != NULL) {
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- cache->hits++;
-#endif
- *entry_return = *slot;
- if (created_entry)
- *created_entry = 0;
- return status;
+ if (! cache->preserve_entries) {
+ while (cache->size + entry->size > cache->max_size) {
+ status = _cairo_cache_remove_random (cache);
+ if (status) {
+ if (status == CAIRO_INT_STATUS_CACHE_EMPTY)
+ break;
+ return status;
+ }
+ }
}
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- cache->misses++;
-#endif
-
- /* Build the new entry. */
- status = cache->backend->create_entry (cache, key,
- (void **)&new_entry);
- if (status != CAIRO_STATUS_SUCCESS)
- return status;
-
- /* Store the hash value in case the backend forgot. */
- new_entry->hashcode = cache->backend->hash (cache, key);
-
- if (cache->live_entries && cache->max_memory)
- _cairo_cache_shrink_to (cache, cache->max_memory);
-
- /* Can't assert this; new_entry->memory may be larger than max_memory */
- /* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */
-
- /* Make room in the table for a new slot. */
- status = _resize_cache (cache, cache->live_entries + 1);
- if (status != CAIRO_STATUS_SUCCESS) {
- cache->backend->destroy_entry (cache, new_entry);
+ status = _cairo_hash_table_insert (cache->hash_table,
+ (cairo_hash_entry_t *) entry);
+ if (status)
return status;
- }
- slot = _find_available_entry_for (cache, key);
- assert(slot != NULL);
-
- /* Store entry in slot and increment statistics. */
- *slot = new_entry;
- cache->live_entries++;
- cache->used_memory += new_entry->memory;
-
- _cache_sane_state (cache);
+ cache->size += entry->size;
- *entry_return = new_entry;
- if (created_entry)
- *created_entry = 1;
-
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_cache_remove (cairo_cache_t *cache,
- void *key)
+/**
+ * _cairo_cache_remove:
+ * @cache: a cache
+ * @entry: key of entry to be removed
+ *
+ * Remove an entry from the cache which has a key that matches @key,
+ * if any (as determined by the keys_equal() function passed to
+ * _cairo_cache_create).
+ **/
+cairo_private void
+_cairo_cache_remove (cairo_cache_t *cache,
+ cairo_cache_entry_t *entry)
{
- cairo_cache_entry_base_t **slot;
-
- _cache_sane_state (cache);
+ cache->size -= entry->size;
- /* See if we have an entry in the table already. */
- slot = _find_exact_live_entry_for (cache, key);
- if (slot != NULL)
- _entry_destroy (cache, slot - cache->entries);
+ _cairo_hash_table_remove (cache->hash_table,
+ (cairo_hash_entry_t *) entry);
- return CAIRO_STATUS_SUCCESS;
+ if (cache->entry_destroy)
+ cache->entry_destroy (entry);
}
-void *
-_cairo_cache_random_entry (cairo_cache_t *cache,
- int (*predicate)(void*))
+/**
+ * _cairo_cache_foreach:
+ * @cache: a cache
+ * @cache_callback: function to be called for each entry
+ * @closure: additional argument to be passed to @cache_callback
+ *
+ * Call @cache_callback for each entry in the cache, in a
+ * non-specified order.
+ **/
+void
+_cairo_cache_foreach (cairo_cache_t *cache,
+ cairo_cache_callback_func_t cache_callback,
+ void *closure)
{
- cairo_cache_entry_base_t **slot = _random_entry (cache, predicate);
-
- return slot ? *slot : NULL;
+ _cairo_hash_table_foreach (cache->hash_table,
+ cache_callback,
+ closure);
}
unsigned long
Index: cairo-debug.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-debug.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cairo-debug.c 1 Aug 2005 20:33:47 -0000 1.1
+++ cairo-debug.c 31 Aug 2005 22:08:02 -0000 1.2
@@ -60,7 +60,6 @@
cairo_debug_reset_static_data (void)
{
#if CAIRO_HAS_XLIB_SURFACE
- _cairo_xlib_surface_reset_static_data ();
_cairo_xlib_screen_reset_static_data ();
#endif
Index: cairo-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-font.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -d -r1.76 -r1.77
--- cairo-font.c 24 Aug 2005 04:36:08 -0000 1.76
+++ cairo-font.c 31 Aug 2005 22:08:02 -0000 1.77
@@ -413,561 +413,6 @@
_cairo_toy_font_face_scaled_font_create
};
-/* cairo_scaled_font_t */
-
-static const cairo_scaled_font_t _cairo_scaled_font_nil = {
- { 0 }, /* hash_entry */
- CAIRO_STATUS_NO_MEMORY, /* status */
- -1, /* ref_count */
- NULL, /* font_face */
- { 1., 0., 0., 1., 0, 0}, /* font_matrix */
- { 1., 0., 0., 1., 0, 0}, /* ctm */
- { 1., 0., 0., 1., 0, 0}, /* scale */
- { CAIRO_ANTIALIAS_DEFAULT, /* options */
- CAIRO_SUBPIXEL_ORDER_DEFAULT,
- CAIRO_HINT_STYLE_DEFAULT,
- CAIRO_HINT_METRICS_DEFAULT} ,
- CAIRO_SCALED_FONT_BACKEND_DEFAULT,
-};
-
-/**
- * _cairo_scaled_font_set_error:
- * @scaled_font: a scaled_font
- * @status: a status value indicating an error, (eg. not
- * CAIRO_STATUS_SUCCESS)
- *
- * Sets scaled_font->status to @status and calls _cairo_error;
- *
- * All assignments of an error status to scaled_font->status should happen
- * through _cairo_scaled_font_set_error() or else _cairo_error() should be
- * called immediately after the assignment.
- *
- * The purpose of this function is to allow the user to set a
- * breakpoint in _cairo_error() to generate a stack trace for when the
- * user causes cairo to detect an error.
- **/
-void
-_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
- cairo_status_t status)
-{
- /* Don't overwrite an existing error. This preserves the first
- * error, which is the most significant. It also avoids attempting
- * to write to read-only data (eg. from a nil scaled_font). */
- if (scaled_font->status == CAIRO_STATUS_SUCCESS)
- scaled_font->status = status;
-
- _cairo_error (status);
-}
-
-/**
- * cairo_scaled_font_status:
- * @scaled_font: a #cairo_scaled_font_t
- *
- * Checks whether an error has previously occurred for this
- * scaled_font.
- *
- * Return value: %CAIRO_STATUS_SUCCESS or another error such as
- * %CAIRO_STATUS_NO_MEMORY.
- **/
-cairo_status_t
-cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
-{
- return scaled_font->status;
-}
-
-/* Here we keep a unique mapping from
- * cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t.
- *
- * Here are the things that we want to map:
- *
- * a) All otherwise referenced cairo_scaled_font_t's
- * b) Some number of not otherwise referenced cairo_scaled_font_t's
- *
- * The implementation uses a hash table which covers (a)
- * completely. Then, for (b) we have an array of otherwise
- * unreferenced fonts (holdovers) which are expired in
- * least-recently-used order.
- *
- * The cairo_scaled_font_create code gets to treat this like a regular
- * hash table. All of the magic for the little holdover cache is in
- * cairo_scaled_font_reference and cairo_scaled_font_destroy.
- */
-
-/* This defines the size of the holdover array ... that is, the number
- * of scaled fonts we keep around even when not otherwise referenced
- */
-#define CAIRO_SCALED_FONT_MAX_HOLDOVERS 24
-
-typedef struct _cairo_scaled_font_map {
- cairo_hash_table_t *hash_table;
- cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS];
- int num_holdovers;
-} cairo_scaled_font_map_t;
-
-static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
-
-CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
-
-static int
-_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
-
-static cairo_scaled_font_map_t *
-_cairo_scaled_font_map_lock (void)
-{
- CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
-
- if (cairo_scaled_font_map == NULL)
- {
- cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t));
- if (cairo_scaled_font_map == NULL)
- goto CLEANUP_MUTEX_LOCK;
-
- cairo_scaled_font_map->hash_table =
- _cairo_hash_table_create (_cairo_scaled_font_keys_equal);
-
- if (cairo_scaled_font_map->hash_table == NULL)
- goto CLEANUP_SCALED_FONT_MAP;
-
- cairo_scaled_font_map->num_holdovers = 0;
- }
-
- return cairo_scaled_font_map;
-
- CLEANUP_SCALED_FONT_MAP:
- free (cairo_scaled_font_map);
- CLEANUP_MUTEX_LOCK:
- CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
- return NULL;
-}
-
-static void
-_cairo_scaled_font_map_unlock (void)
-{
- CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
-}
-
-static void
-_cairo_scaled_font_map_destroy (void)
-{
- int i;
- cairo_scaled_font_map_t *font_map = cairo_scaled_font_map;
- cairo_scaled_font_t *scaled_font;
-
- if (font_map == NULL)
- return;
-
- CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
-
- for (i = 0; i < font_map->num_holdovers; i++) {
- scaled_font = font_map->holdovers[i];
- /* We should only get here through the reset_static_data path
- * and there had better not be any active references at that
- * point. */
- assert (scaled_font->ref_count == 0);
- _cairo_hash_table_remove (font_map->hash_table,
- &scaled_font->hash_entry);
- _cairo_scaled_font_fini (scaled_font);
- free (scaled_font);
- }
-
- _cairo_hash_table_destroy (font_map->hash_table);
-
- free (cairo_scaled_font_map);
- cairo_scaled_font_map = NULL;
-}
-
-/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
- *
- * Not necessarily better than a lot of other hashes, but should be OK, and
- * well tested with binary data.
- */
-
-#define FNV_32_PRIME ((uint32_t)0x01000193)
-#define FNV1_32_INIT ((uint32_t)0x811c9dc5)
-
-static uint32_t
-_hash_bytes_fnv (unsigned char *buffer,
- int len,
- uint32_t hval)
-{
- while (len--) {
- hval *= FNV_32_PRIME;
- hval ^= *buffer++;
- }
-
- return hval;
-}
-
-static void
-_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
- cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options)
-{
- uint32_t hash = FNV1_32_INIT;
-
- scaled_font->status = CAIRO_STATUS_SUCCESS;
- scaled_font->font_face = font_face;
- scaled_font->font_matrix = *font_matrix;
- scaled_font->ctm = *ctm;
- scaled_font->options = *options;
-
- /* We do a bytewise hash on the font matrices, ignoring the
- * translation values. */
- hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx),
- sizeof(double) * 4,
- hash);
- hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx),
- sizeof(double) * 4,
- hash);
-
- hash ^= (unsigned long) scaled_font->font_face;
-
- hash ^= cairo_font_options_hash (&scaled_font->options);
-
- scaled_font->hash_entry.hash = hash;
-}
-
-static cairo_bool_t
-_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
-{
- cairo_scaled_font_t *key_a = abstract_key_a;
- cairo_scaled_font_t *key_b = abstract_key_b;
-
- return (key_a->font_face == key_b->font_face &&
- memcmp ((unsigned char *)(&key_a->font_matrix.xx),
- (unsigned char *)(&key_b->font_matrix.xx),
- sizeof(double) * 4) == 0 &&
- memcmp ((unsigned char *)(&key_a->ctm.xx),
- (unsigned char *)(&key_b->ctm.xx),
- sizeof(double) * 4) == 0 &&
- cairo_font_options_equal (&key_a->options, &key_b->options));
-}
-
-void
-_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
- cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- const cairo_scaled_font_backend_t *backend)
-{
- scaled_font->ref_count = 1;
-
- _cairo_scaled_font_init_key (scaled_font, font_face,
- font_matrix, ctm, options);
-
- cairo_font_face_reference (font_face);
-
- cairo_matrix_multiply (&scaled_font->scale,
- &scaled_font->font_matrix,
- &scaled_font->ctm);
-
- scaled_font->backend = backend;
-}
-
-void
-_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
-{
- if (scaled_font->font_face)
- cairo_font_face_destroy (scaled_font->font_face);
-
- scaled_font->backend->fini (scaled_font);
-}
-
-/**
- * cairo_scaled_font_create:
- * @font_face: a #cairo_font_face_t
- * @font_matrix: font space to user space transformation matrix for the
- * font. In the simplest case of a N point font, this matrix is
- * just a scale by N, but it can also be used to shear the font
- * or stretch it unequally along the two axes. See
- * cairo_set_font_matrix().
- * @ctm: user to device transformation matrix with which the font will
- * be used.
- * @options: options to use when getting metrics for the font and
- * rendering with it.
- *
- * Creates a #cairo_scaled_font_t object from a font face and matrices that
- * describe the size of the font and the environment in which it will
- * be used.
- *
- * Return value: a newly created #cairo_scaled_font_t. Destroy with
- * cairo_scaled_font_destroy()
- **/
-cairo_scaled_font_t *
-cairo_scaled_font_create (cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options)
-{
- cairo_status_t status;
- cairo_scaled_font_map_t *font_map;
- cairo_scaled_font_t key, *scaled_font = NULL;
-
- font_map = _cairo_scaled_font_map_lock ();
- if (font_map == NULL)
- goto UNWIND;
-
- _cairo_scaled_font_init_key (&key, font_face,
- font_matrix, ctm, options);
-
- /* Return existing scaled_font if it exists in the hash table. */
- if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
- (cairo_hash_entry_t**) &scaled_font))
- {
- _cairo_scaled_font_map_unlock ();
- return cairo_scaled_font_reference (scaled_font);
- }
-
- /* Otherwise create it and insert it into the hash table. */
- status = font_face->backend->scaled_font_create (font_face, font_matrix,
- ctm, options, &scaled_font);
- if (status)
- goto UNWIND_FONT_MAP_LOCK;
-
- status = _cairo_hash_table_insert (font_map->hash_table,
- &scaled_font->hash_entry);
- if (status)
- goto UNWIND_SCALED_FONT_CREATE;
-
- _cairo_scaled_font_map_unlock ();
-
- return scaled_font;
-
-UNWIND_SCALED_FONT_CREATE:
- /* 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);
- free (scaled_font);
-UNWIND_FONT_MAP_LOCK:
- _cairo_scaled_font_map_unlock ();
-UNWIND:
- return NULL;
-}
-
-/**
- * cairo_scaled_font_reference:
- * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case
- * this function does nothing)
- *
- * Increases the reference count on @scaled_font by one. This prevents
- * @scaled_font from being destroyed until a matching call to
- * cairo_scaled_font_destroy() is made.
- *
- * Returns: the referenced #cairo_scaled_font_t
- **/
-cairo_scaled_font_t *
-cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
-{
- if (scaled_font == NULL)
- return NULL;
-
- if (scaled_font->ref_count == (unsigned int)-1)
- return scaled_font;
-
- /* We would normally assert (scaled_font->ref_count > 0) here, but
- * we are using ref_count == 0 as a legitimate case for the
- * holdovers array. See below. */
-
- /* If the original reference count is 0, then this font must have
- * been found in font_map->holdovers, (which means this caching is
- * actually working). So now we remove it from the holdovers
- * array. */
- if (scaled_font->ref_count == 0) {
- cairo_scaled_font_map_t *font_map;
- int i;
-
- font_map = _cairo_scaled_font_map_lock ();
- {
- for (i = 0; i < font_map->num_holdovers; i++)
- if (font_map->holdovers[i] == scaled_font)
- break;
- assert (i < font_map->num_holdovers);
-
- font_map->num_holdovers--;
- memmove (&font_map->holdovers[i],
- &font_map->holdovers[i+1],
- (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
- }
- _cairo_scaled_font_map_unlock ();
- }
-
- scaled_font->ref_count++;
-
- return scaled_font;
-}
-
-/**
- * cairo_scaled_font_destroy:
- * @scaled_font: a #cairo_scaled_font_t
- *
- * Decreases the reference count on @font by one. If the result
- * is zero, then @font and all associated resources are freed.
- * See cairo_scaled_font_reference().
- **/
-void
-cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
-{
- cairo_scaled_font_map_t *font_map;
-
- if (scaled_font == NULL)
- return;
-
- if (scaled_font->ref_count == (unsigned int)-1)
- return;
-
- assert (scaled_font->ref_count > 0);
-
- if (--(scaled_font->ref_count) > 0)
- return;
-
- font_map = _cairo_scaled_font_map_lock ();
- assert (font_map != NULL);
- {
- /* Rather than immediately destroying this object, we put it into
- * the font_map->holdovers array in case it will get used again
- * soon. To make room for it, we do actually destroy the
- * least-recently-used holdover.
- */
- if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
- cairo_scaled_font_t *lru;
-
- lru = font_map->holdovers[0];
- assert (lru->ref_count == 0);
-
- _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
-
- _cairo_scaled_font_fini (lru);
- free (lru);
-
- font_map->num_holdovers--;
- memmove (&font_map->holdovers[0],
- &font_map->holdovers[1],
- font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
- }
-
- font_map->holdovers[font_map->num_holdovers] = scaled_font;
- font_map->num_holdovers++;
- }
- _cairo_scaled_font_map_unlock ();
-}
-
-cairo_status_t
-_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
- const char *utf8,
- cairo_glyph_t **glyphs,
- int *num_glyphs)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- return scaled_font->backend->text_to_glyphs (scaled_font, utf8, glyphs, num_glyphs);
-}
-
-cairo_status_t
-_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- return scaled_font->backend->glyph_extents (scaled_font, glyphs, num_glyphs, extents);
-}
-
-
-cairo_status_t
-_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- return scaled_font->backend->glyph_bbox (scaled_font, glyphs, num_glyphs, bbox);
-}
-
-cairo_status_t
-_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
- cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- cairo_glyph_t *glyphs,
- int num_glyphs)
-{
- cairo_status_t status;
-
- /* These operators aren't interpreted the same way by the backends;
- * they are implemented in terms of other operators in cairo-gstate.c
- */
- assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
-
- if (scaled_font->status)
- return scaled_font->status;
-
- status = _cairo_surface_show_glyphs (scaled_font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- /* Surface display routine either does not exist or failed. */
- return scaled_font->backend->show_glyphs (scaled_font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
-}
-
-cairo_status_t
-_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_fixed_t *path)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- return scaled_font->backend->glyph_path (scaled_font, glyphs, num_glyphs, path);
-}
-
-cairo_status_t
-_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
- cairo_glyph_cache_key_t *key)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- scaled_font->backend->get_glyph_cache_key (scaled_font, key);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
- cairo_font_extents_t *extents)
-{
- if (scaled_font->status)
- return scaled_font->status;
-
- return scaled_font->backend->font_extents (scaled_font, extents);
-}
-
void
_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
const cairo_unscaled_font_backend_t *backend)
@@ -1001,303 +446,11 @@
free (unscaled_font);
}
-/* Public font API follows. */
-
-/**
- * cairo_scaled_font_extents:
- * @scaled_font: a #cairo_scaled_font_t
- * @extents: a #cairo_font_extents_t which to store the retrieved extents.
- *
- * Gets the metrics for a #cairo_scaled_font_t.
- **/
-void
-cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
- cairo_font_extents_t *extents)
-{
- cairo_int_status_t status;
- double font_scale_x, font_scale_y;
-
- if (scaled_font->status)
- return;
-
- status = _cairo_scaled_font_font_extents (scaled_font, extents);
- if (status) {
- _cairo_scaled_font_set_error (scaled_font, status);
- return;
- }
-
- _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
- &font_scale_x, &font_scale_y,
- /* XXX */ 1);
-
- /*
- * The font responded in unscaled units, scale by the font
- * matrix scale factors to get to user space
- */
-
- extents->ascent *= font_scale_y;
- extents->descent *= font_scale_y;
- extents->height *= font_scale_y;
- extents->max_x_advance *= font_scale_x;
- extents->max_y_advance *= font_scale_y;
-}
-
-/**
- * cairo_font_glyph_extents:
- * @scaled_font: a #cairo_scaled_font_t
- * @glyphs: an array of glyph IDs with X and Y offsets.
- * @num_glyphs: the number of glyphs in the @glyphs array
- * @extents: a #cairo_text_extents_t which to store the retrieved extents.
- *
- * cairo_font_glyph_extents() gets the overall metrics for a string of
- * glyphs. The X and Y offsets in @glyphs are taken from an origin of 0,0.
- **/
-void
-cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
-{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_glyph_t origin_glyph;
- cairo_text_extents_t origin_extents;
- int i;
- double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
- double x_pos = 0.0, y_pos = 0.0;
- int set = 0;
-
- if (scaled_font->status)
- return;
-
- if (!num_glyphs)
- {
- extents->x_bearing = 0.0;
- extents->y_bearing = 0.0;
- extents->width = 0.0;
- extents->height = 0.0;
- extents->x_advance = 0.0;
- extents->y_advance = 0.0;
-
- return;
- }
-
- for (i = 0; i < num_glyphs; i++)
- {
- double x, y;
- double wm, hm;
-
- origin_glyph = glyphs[i];
- origin_glyph.x = 0.0;
- origin_glyph.y = 0.0;
- status = _cairo_scaled_font_glyph_extents (scaled_font,
- &origin_glyph, 1,
- &origin_extents);
-
- /*
- * Transform font space metrics into user space metrics
- * by running the corners through the font matrix and
- * expanding the bounding box as necessary
- */
- x = origin_extents.x_bearing;
- y = origin_extents.y_bearing;
- cairo_matrix_transform_point (&scaled_font->font_matrix,
- &x, &y);
-
- for (hm = 0.0; hm <= 1.0; hm += 1.0)
- for (wm = 0.0; wm <= 1.0; wm += 1.0)
- {
- x = origin_extents.x_bearing + origin_extents.width * wm;
- y = origin_extents.y_bearing + origin_extents.height * hm;
- cairo_matrix_transform_point (&scaled_font->font_matrix,
- &x, &y);
- x += glyphs[i].x;
- y += glyphs[i].y;
- if (!set)
- {
- min_x = max_x = x;
- min_y = max_y = y;
- set = 1;
- }
- else
- {
- if (x < min_x) min_x = x;
- if (x > max_x) max_x = x;
- if (y < min_y) min_y = y;
- if (y > max_y) max_y = y;
- }
- }
-
- x = origin_extents.x_advance;
- y = origin_extents.y_advance;
- cairo_matrix_transform_point (&scaled_font->font_matrix,
- &x, &y);
- x_pos = glyphs[i].x + x;
- y_pos = glyphs[i].y + y;
- }
-
- extents->x_bearing = min_x - glyphs[0].x;
- extents->y_bearing = min_y - glyphs[0].y;
- extents->width = max_x - min_x;
- extents->height = max_y - min_y;
- extents->x_advance = x_pos - glyphs[0].x;
- extents->y_advance = y_pos - glyphs[0].y;
-}
-
-/* Now we implement functions to access a default global image & metrics
- * cache.
- */
-
-unsigned long
-_cairo_glyph_cache_hash (void *cache, void *key)
-{
- cairo_glyph_cache_key_t *in;
- in = (cairo_glyph_cache_key_t *) key;
- return
- ((unsigned long) in->unscaled)
- ^ ((unsigned long) in->scale.xx)
- ^ ((unsigned long) in->scale.yx)
- ^ ((unsigned long) in->scale.xy)
- ^ ((unsigned long) in->scale.yy)
- ^ (in->flags * 1451) /* 1451 is just an abitrary prime */
- ^ in->index;
-}
-
-int
-_cairo_glyph_cache_keys_equal (void *cache,
- void *k1,
- void *k2)
-{
- cairo_glyph_cache_key_t *a, *b;
- a = (cairo_glyph_cache_key_t *) k1;
- b = (cairo_glyph_cache_key_t *) k2;
- return (a->index == b->index)
- && (a->unscaled == b->unscaled)
- && (a->flags == b->flags)
- && (a->scale.xx == b->scale.xx)
- && (a->scale.yx == b->scale.yx)
- && (a->scale.xy == b->scale.xy)
- && (a->scale.yy == b->scale.yy);
-}
-
-
-static cairo_status_t
-_image_glyph_cache_create_entry (void *cache,
- void *key,
- void **return_value)
-{
- cairo_glyph_cache_key_t *k = (cairo_glyph_cache_key_t *) key;
- cairo_image_glyph_cache_entry_t *im;
- cairo_status_t status;
-
- im = calloc (1, sizeof (cairo_image_glyph_cache_entry_t));
- if (im == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- im->key = *k;
- status = im->key.unscaled->backend->create_glyph (im->key.unscaled,
- im);
-
- if (status != CAIRO_STATUS_SUCCESS) {
- free (im);
- return status;
- }
-
- _cairo_unscaled_font_reference (im->key.unscaled);
-
- im->key.base.memory =
- sizeof (cairo_image_glyph_cache_entry_t)
- + (im->image ?
- sizeof (cairo_image_surface_t)
- + 28 * sizeof (int) /* rough guess at size of pixman image structure */
- + (im->image->height * im->image->stride) : 0);
-
- *return_value = im;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-static void
-_image_glyph_cache_destroy_entry (void *cache,
- void *value)
-{
- cairo_image_glyph_cache_entry_t *im;
-
- im = (cairo_image_glyph_cache_entry_t *) value;
- _cairo_unscaled_font_destroy (im->key.unscaled);
- cairo_surface_destroy (&(im->image->base));
- free (im);
-}
-
-static void
-_image_glyph_cache_destroy_cache (void *cache)
-{
- free (cache);
-}
-
-static const cairo_cache_backend_t cairo_image_cache_backend = {
- _cairo_glyph_cache_hash,
- _cairo_glyph_cache_keys_equal,
- _image_glyph_cache_create_entry,
- _image_glyph_cache_destroy_entry,
- _image_glyph_cache_destroy_cache
-};
-
-CAIRO_MUTEX_DECLARE(_global_image_glyph_cache_mutex);
-
-static cairo_cache_t *
-_global_image_glyph_cache = NULL;
-
-void
-_cairo_lock_global_image_glyph_cache (void)
-{
- CAIRO_MUTEX_LOCK (_global_image_glyph_cache_mutex);
-}
-
-void
-_cairo_unlock_global_image_glyph_cache (void)
-{
- if (_global_image_glyph_cache) {
- _cairo_cache_shrink_to (_global_image_glyph_cache,
- CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
- }
- CAIRO_MUTEX_UNLOCK (_global_image_glyph_cache_mutex);
-}
-
-cairo_cache_t *
-_cairo_get_global_image_glyph_cache (void)
-{
- if (_global_image_glyph_cache == NULL) {
- _global_image_glyph_cache = malloc (sizeof (cairo_cache_t));
-
- if (_global_image_glyph_cache == NULL)
- goto FAIL;
-
- if (_cairo_cache_init (_global_image_glyph_cache,
- &cairo_image_cache_backend,
- 0))
- goto FAIL;
- }
-
- return _global_image_glyph_cache;
-
- FAIL:
- if (_global_image_glyph_cache)
- free (_global_image_glyph_cache);
- _global_image_glyph_cache = NULL;
- return NULL;
-}
-
void
_cairo_font_reset_static_data (void)
{
_cairo_scaled_font_map_destroy ();
- _cairo_lock_global_image_glyph_cache();
- _cairo_cache_destroy (_global_image_glyph_cache);
- _global_image_glyph_cache = NULL;
- _cairo_unlock_global_image_glyph_cache();
-
CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
_cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
cairo_toy_font_face_hash_table = NULL;
Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -u -d -r1.110 -r1.111
--- cairo-ft-font.c 24 Aug 2005 02:52:09 -0000 1.110
+++ cairo-ft-font.c 31 Aug 2005 22:08:02 -0000 1.111
@@ -57,20 +57,6 @@
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
-/* We pack some of our own information into the bits unused
- * by FreeType's load flags. If FreeType ever uses up all
- * the load flag bits, we'll have to do something else.
- * (probably just store what we care about in load_flags
- * then convert into FreeType terms.
- */
-#define PRIVATE_FLAG_HINT_METRICS (0x01 << 24)
-#define PRIVATE_FLAG_EMBOLDEN (0x02 << 24)
[...1526 lines suppressed...]
@@ -2533,6 +2213,7 @@
{
cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
+ cairo_ft_options_t ft_options;
unscaled = _cairo_ft_unscaled_font_create_from_face (face);
if (unscaled == NULL) {
@@ -2540,7 +2221,10 @@
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
- font_face = _cairo_ft_font_face_create (unscaled, load_flags);
+ ft_options.load_flags = load_flags;
+ ft_options.extra_flags = 0;
+
+ font_face = _cairo_ft_font_face_create (unscaled, ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face) {
Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.168
retrieving revision 1.169
diff -u -d -r1.168 -r1.169
--- cairo-gstate.c 24 Aug 2005 08:39:56 -0000 1.168
+++ cairo-gstate.c 31 Aug 2005 22:08:02 -0000 1.169
@@ -1950,30 +1950,17 @@
int *num_glyphs)
{
cairo_status_t status;
- int i;
status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
- status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font,
+ status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
utf8, glyphs, num_glyphs);
if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
return status;
- /* The font responded in glyph space, starting from (0,0). Convert to
- user space by applying the font transform, then add any current point
- offset. */
-
- for (i = 0; i < *num_glyphs; ++i) {
- cairo_matrix_transform_point (&gstate->font_matrix,
- &((*glyphs)[i].x),
- &((*glyphs)[i].y));
- (*glyphs)[i].x += x;
- (*glyphs)[i].y += y;
- }
-
return CAIRO_STATUS_SUCCESS;
}
@@ -2050,6 +2037,17 @@
if (!src)
src = &pattern.base;
+ status = _cairo_surface_show_glyphs (glyph_info->font, operator, src,
+ dst,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height,
+ glyph_info->glyphs,
+ glyph_info->num_glyphs);
+
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
status = _cairo_scaled_font_show_glyphs (glyph_info->font,
operator,
src, dst,
@@ -2074,7 +2072,6 @@
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_pattern_union_t pattern;
- cairo_box_t bbox;
cairo_rectangle_t extents;
cairo_show_glyphs_info_t glyph_info;
@@ -2102,21 +2099,15 @@
}
if (_cairo_operator_bounded (gstate->operator))
- {
- status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
- transformed_glyphs, num_glyphs,
- &bbox);
- if (status)
- goto CLEANUP_GLYPHS;
-
- _cairo_box_round_to_rectangle (&bbox, &extents);
- }
+ status = _cairo_scaled_font_glyph_device_extents (gstate->scaled_font,
+ transformed_glyphs,
+ num_glyphs,
+ &extents);
else
- {
status = _cairo_surface_get_extents (gstate->target, &extents);
- if (status)
- goto CLEANUP_GLYPHS;
- }
+
+ if (status)
+ goto CLEANUP_GLYPHS;
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
if (status)
Index: cairo-path.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-path.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- cairo-path.c 3 May 2005 21:28:50 -0000 1.27
+++ cairo-path.c 31 Aug 2005 22:08:02 -0000 1.28
@@ -132,6 +132,17 @@
return CAIRO_STATUS_SUCCESS;
}
+cairo_path_fixed_t *
+_cairo_path_fixed_create (void)
+{
+ cairo_path_fixed_t *path = malloc (sizeof (cairo_path_fixed_t));
+
+ if (!path)
+ return NULL;
+ _cairo_path_fixed_init (path);
+ return path;
+}
+
void
_cairo_path_fixed_fini (cairo_path_fixed_t *path)
{
@@ -155,6 +166,13 @@
path->has_current_point = 0;
}
+void
+_cairo_path_fixed_destroy (cairo_path_fixed_t *path)
+{
+ _cairo_path_fixed_fini (path);
+ free (path);
+}
+
cairo_status_t
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
--- NEW FILE: cairo-scaled-font.c ---
(This appears to be a binary file; contents omitted.)
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.118
retrieving revision 1.119
diff -u -d -r1.118 -r1.119
--- cairo-xlib-surface.c 30 Aug 2005 17:50:27 -0000 1.118
+++ cairo-xlib-surface.c 31 Aug 2005 22:08:02 -0000 1.119
@@ -192,16 +192,15 @@
}
static cairo_surface_t *
-_cairo_xlib_surface_create_similar (void *abstract_src,
- cairo_content_t content,
- int width,
- int height)
+_cairo_xlib_surface_create_similar_with_format (void *abstract_src,
+ cairo_format_t format,
+ int width,
+ int height)
[...1058 lines suppressed...]
-
-static void
-_destroy_glyphset_cache_recurse (glyphset_cache_t *cache)
-{
- if (cache == NULL)
- return;
-
- _destroy_glyphset_cache_recurse (cache->next);
- _cairo_cache_destroy (&cache->base);
- free (cache);
-}
-
-void
-_cairo_xlib_surface_reset_static_data (void)
-{
- _lock_xlib_glyphset_caches ();
- _destroy_glyphset_cache_recurse (_xlib_glyphset_caches);
- _xlib_glyphset_caches = NULL;
- _unlock_xlib_glyphset_caches (NULL);
-}
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.207
retrieving revision 1.208
diff -u -d -r1.207 -r1.208
--- cairoint.h 28 Aug 2005 01:46:34 -0000 1.207
+++ cairoint.h 31 Aug 2005 22:08:02 -0000 1.208
@@ -184,6 +184,7 @@
#define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0)
#include "cairo-hash-private.h"
+#include "cairo-cache-private.h"
typedef struct _cairo_point {
cairo_fixed_t x;
@@ -227,7 +228,8 @@
typedef enum cairo_int_status {
CAIRO_INT_STATUS_DEGENERATE = 1000,
CAIRO_INT_STATUS_UNSUPPORTED,
- CAIRO_INT_STATUS_NOTHING_TO_DO
+ CAIRO_INT_STATUS_NOTHING_TO_DO,
+ CAIRO_INT_STATUS_CACHE_EMPTY
} cairo_int_status_t;
typedef enum cairo_direction {
@@ -288,6 +290,8 @@
typedef struct _cairo_color cairo_color_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
+typedef struct _cairo_surface_backend cairo_surface_backend_t;
+
cairo_private void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle);
@@ -348,108 +352,9 @@
void *user_data,
cairo_destroy_func_t destroy);
-/* cairo_cache.c structures and functions */
-
-typedef struct _cairo_cache_backend {
-
- unsigned long (*hash) (void *cache,
- void *key);
-
- int (*keys_equal) (void *cache,
- void *k1,
- void *k2);
-
- cairo_status_t (*create_entry) (void *cache,
- void *key,
- void **entry_return);
-
- void (*destroy_entry) (void *cache,
- void *entry);
-
- void (*destroy_cache) (void *cache);
-
-} cairo_cache_backend_t;
-
-/*
- * The cairo_cache system makes the following assumptions about
- * entries in its cache:
- *
- * - a pointer to an entry can be cast to a cairo_cache_entry_base_t.
- * - a pointer to an entry can also be cast to the "key type".
- *
- * The practical effect of this is that your entries must be laid
- * out this way:
- *
- * struct my_entry {
- * cairo_cache_entry_base_t;
- * my_key_value_1;
- * my_key_value_2;
- * ...
- * my_value;
- * };
- */
-
-typedef struct {
- unsigned long memory;
- unsigned long hashcode;
-} cairo_cache_entry_base_t;
-
-typedef struct {
- unsigned long high_water_mark;
- unsigned long size;
- unsigned long rehash;
-} cairo_cache_arrangement_t;
-
-#undef CAIRO_MEASURE_CACHE_PERFORMANCE
-
-typedef struct {
- const cairo_cache_backend_t *backend;
- const cairo_cache_arrangement_t *arrangement;
- cairo_cache_entry_base_t **entries;
-
- unsigned long max_memory;
- unsigned long used_memory;
- unsigned long live_entries;
-
-#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
- unsigned long hits;
- unsigned long misses;
- unsigned long probes;
-#endif
-} cairo_cache_t;
-
-cairo_private cairo_status_t
-_cairo_cache_init (cairo_cache_t *cache,
- const cairo_cache_backend_t *backend,
- unsigned long max_memory);
-
-cairo_private void
-_cairo_cache_destroy (cairo_cache_t *cache);
-
-cairo_private void
-_cairo_cache_shrink_to (cairo_cache_t *cache,
- unsigned long max_memory);
-
-cairo_private cairo_status_t
-_cairo_cache_lookup (cairo_cache_t *cache,
- void *key,
- void **entry_return,
- int *created_entry);
-
-cairo_private cairo_status_t
-_cairo_cache_remove (cairo_cache_t *cache,
- void *key);
-
-cairo_private void *
-_cairo_cache_random_entry (cairo_cache_t *cache,
- int (*predicate) (void*));
-
cairo_private unsigned long
_cairo_hash_string (const char *c);
-#define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
-#define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
-
typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
@@ -471,16 +376,47 @@
cairo_hint_metrics_t hint_metrics;
};
+typedef struct _cairo_scaled_glyph {
+ cairo_cache_entry_t cache_entry; /* hash is glyph index */
+ cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
+ cairo_text_extents_t metrics; /* user-space metrics */
+ cairo_box_t bbox; /* device-space bounds */
+ cairo_image_surface_t *surface; /* device-space image */
+ cairo_path_fixed_t *path; /* device-space outline */
+ 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))
+
struct _cairo_scaled_font {
+ /* must be first to be stored in a hash table */
cairo_hash_entry_t hash_entry;
+
+ /* useful bits for _cairo_scaled_font_nil */
cairo_status_t status;
int ref_count;
+
+ /* hash key members */
cairo_font_face_t *font_face; /* may be NULL */
cairo_matrix_t font_matrix; /* font space => user space */
cairo_matrix_t ctm; /* user space => device space */
- cairo_matrix_t scale; /* font space => device space */
cairo_font_options_t options;
-
+
+ /* "live" scaled_font members */
+ cairo_matrix_t scale; /* font space => device space */
+ cairo_font_extents_t extents; /* user space */
+ cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */
+
+ /*
+ * One surface backend may store data in each glyph.
+ * Whichever surface manages to store its pointer here
+ * first gets to store data in each glyph
+ */
+ const cairo_surface_backend_t *surface_backend;
+ void *surface_private;
+
+ /* font backend managing this scaled font */
const cairo_scaled_font_backend_t *backend;
};
@@ -492,40 +428,6 @@
const cairo_font_face_backend_t *backend;
};
-/* cairo_font.c is responsible for a global glyph cache:
- *
- * - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index],
- * image, size, extents]
- *
- * Surfaces may build their own glyph caches if they have surface-specific
- * glyph resources to maintain; those caches can feed off of the global
- * caches if need be (eg. cairo_xlib_surface.c does this).
- */
-
-typedef struct {
- cairo_cache_entry_base_t base;
- cairo_unscaled_font_t *unscaled;
- cairo_matrix_t scale; /* translation is ignored */
- int flags;
- unsigned long index;
-} cairo_glyph_cache_key_t;
-
-typedef struct {
- cairo_glyph_cache_key_t key;
- cairo_image_surface_t *image;
- cairo_glyph_size_t size;
- cairo_text_extents_t extents;
-} cairo_image_glyph_cache_entry_t;
-
-cairo_private void
-_cairo_lock_global_image_glyph_cache (void);
-
-cairo_private void
-_cairo_unlock_global_image_glyph_cache (void);
-
-cairo_private cairo_cache_t *
-_cairo_get_global_image_glyph_cache (void);
-
cairo_private void
_cairo_font_reset_static_data (void);
@@ -538,22 +440,10 @@
cairo_private void
_cairo_xlib_screen_reset_static_data (void);
-/* Some glyph cache functions you can reuse. */
-
-cairo_private unsigned long
-_cairo_glyph_cache_hash (void *cache, void *key);
-
-cairo_private int
-_cairo_glyph_cache_keys_equal (void *cache,
- void *k1,
- void *k2);
-
/* the font backend interface */
struct _cairo_unscaled_font_backend {
void (*destroy) (void *unscaled_font);
- cairo_status_t (*create_glyph) (void *unscaled_font,
- cairo_image_glyph_cache_entry_t *entry);
};
/* cairo_toy_font_face_t - simple family/slant/weight font faces used for
@@ -568,6 +458,12 @@
cairo_font_weight_t weight;
} cairo_toy_font_face_t;
+typedef enum _cairo_scaled_glyph_info {
+ CAIRO_SCALED_GLYPH_INFO_METRICS = (1 << 0),
+ CAIRO_SCALED_GLYPH_INFO_SURFACE = (1 << 1),
+ CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2)
+} cairo_scaled_glyph_info_t;
+
struct _cairo_scaled_font_backend {
cairo_status_t
(*create_toy) (cairo_toy_font_face_t *toy_face,
@@ -580,28 +476,14 @@
(*fini) (void *scaled_font);
cairo_status_t
- (*font_extents) (void *scaled_font,
- cairo_font_extents_t *extents);
-
- cairo_status_t
- (*text_to_glyphs) (void *scaled_font,
- const char *utf8,
- cairo_glyph_t **glyphs,
- int *num_glyphs);
-
- cairo_status_t
- (*glyph_extents) (void *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents);
-
- cairo_status_t
- (*glyph_bbox) (void *scaled_font,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox);
+ (*scaled_glyph_init) (void *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_glyph_info_t info);
- cairo_status_t
+ unsigned long
+ (*ucs4_to_index) (void *scaled_font,
+ uint32_t ucs4);
+ cairo_int_status_t
(*show_glyphs) (void *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
@@ -615,15 +497,6 @@
const cairo_glyph_t *glyphs,
int num_glyphs);
- cairo_status_t
- (*glyph_path) (void *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_fixed_t *path);
-
- void
- (*get_glyph_cache_key) (void *scaled_font,
- cairo_glyph_cache_key_t *key);
};
struct _cairo_font_face_backend {
@@ -660,7 +533,7 @@
#endif
-typedef struct _cairo_surface_backend {
+struct _cairo_surface_backend {
cairo_surface_t *
(*create_similar) (void *surface,
cairo_content_t content,
@@ -796,8 +669,8 @@
/*
* This is an optional entry to let the surface manage its own glyph
- * resources. If null, the font will be asked to render against this
- * surface, using image surfaces as glyphs.
+ * resources. If null, render against this surface, using image
+ * surfaces as glyphs.
*/
cairo_int_status_t
(*show_glyphs) (cairo_scaled_font_t *font,
@@ -835,7 +708,13 @@
int width,
int height);
-} cairo_surface_backend_t;
+ void
+ (*scaled_font_fini) (cairo_scaled_font_t *scaled_font);
+
+ void
+ (*scaled_glyph_fini) (cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_font_t *scaled_font);
+};
typedef struct _cairo_format_masks {
int bpp;
@@ -1384,63 +1263,6 @@
cairo_private void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
-cairo_private void
-_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
- cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- const cairo_scaled_font_backend_t *backend);
-
-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);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
- const char *utf8,
- cairo_glyph_t **glyphs,
- int *num_glyphs);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
- cairo_operator_t operator,
- cairo_pattern_t *source,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- cairo_glyph_t *glyphs,
- int num_glyphs);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_fixed_t *path);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
- cairo_glyph_cache_key_t *key);
-
/* cairo-font-options.c */
cairo_private void
@@ -1458,9 +1280,15 @@
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
cairo_path_fixed_t *other);
+cairo_path_fixed_t *
+_cairo_path_fixed_create (void);
+
cairo_private void
_cairo_path_fixed_fini (cairo_path_fixed_t *path);
+void
+_cairo_path_fixed_destroy (cairo_path_fixed_t *path);
+
cairo_private cairo_status_t
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_fixed_t x,
@@ -1545,6 +1373,91 @@
cairo_gstate_t *gstate,
cairo_traps_t *traps);
+/* cairo-scaled-font.c */
+
+cairo_private cairo_status_t
+_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
+ cairo_font_face_t *font_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ const cairo_scaled_font_backend_t *backend);
+
+cairo_private void
+_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
+ cairo_font_extents_t *fs_metrics);
+
+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);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
+ double x,
+ double y,
+ const char *utf8,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_rectangle_t *extents);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
+ cairo_operator_t operator,
+ cairo_pattern_t *source,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ cairo_glyph_t *glyphs,
+ int num_glyphs);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path);
+
+cairo_private void
+_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_font_t *scaled_font,
+ cairo_text_extents_t *fs_metrics);
+
+cairo_private void
+_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_font_t *scaled_font,
+ cairo_image_surface_t *surface);
+
+cairo_private void
+_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_font_t *scaled_font,
+ cairo_path_fixed_t *path);
+
+cairo_status_t
+_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
+ unsigned long index,
+ cairo_scaled_glyph_info_t info,
+ cairo_scaled_glyph_t **scaled_glyph_ret);
+
+cairo_private void
+_cairo_scaled_font_map_destroy (void);
+
/* cairo-surface.c */
extern const cairo_private cairo_surface_t _cairo_surface_nil;
- Previous message: [cairo-commit] cairo ChangeLog,1.1027,1.1028
- Next message: [cairo-commit] cairo/test clip-operator-ref.png, 1.4,
1.5 operator-clear-ref.png, 1.2, 1.3 operator-source-ref.png,
1.2, 1.3 text-antialias-gray-ref.png, 1.2,
1.3 text-antialias-gray.c, 1.2,
1.3 text-antialias-none-ref.png, 1.2,
1.3 text-antialias-none.c, 1.3,
1.4 text-antialias-subpixel-ref.png, 1.3,
1.4 text-antialias-subpixel.c, 1.3,
1.4 unbounded-operator-ref.png, 1.3, 1.4
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list