diff options
author | Owen Taylor <otaylor@redhat.com> | 2005-04-08 13:14:17 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@redhat.com> | 2005-04-08 13:14:17 +0000 |
commit | c803908d95d0022463d138f0caee949b14d0cadb (patch) | |
tree | 7e93e35f8e335c977b466f1a998a3cb03d80c3a0 /src/cairo-array.c | |
parent | 7aa5b71e8cc42bdcc935ad0990a0ac434dd0aa0e (diff) |
src/cairo.h src/cairo-font.c src/cairoint.h doc/public/cairo-sections.txt: Add cairo_font_face_set/get_user_data().
src/cairo-array.c src/cairoint.h src/cairo-surface.c: Refactor user data code from cairo-surface.c into cairo_user_data_array_t.
Switch these types to be like cairo_surface_t where the generic code frees the wrapper object.
src/cairo-atsui-font.c src/cairo-ft-font.c src/cairo-win32-font.c: Fix up for the above changes.
Implement a complicated mutual-referencing scheme to make sure that a face from cairo_ft_font_face_create_for_ft_face() is freed only when the FT_Face is no longer needed.
Update the docs to describe how to figure out when the FT_Face can be freed.
Fix refcount leaks when creating fonts.
Remove excess call to _cairo_unscaled_font_reference().
Remove stray initialization of font matrix to the identity.
test/user-data.c: Fix a bug when setting/unsetting a key with a free key slot before it, add that to the test case.
Don't append an element when user_data is NULL.
Diffstat (limited to 'src/cairo-array.c')
-rw-r--r-- | src/cairo-array.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/cairo-array.c b/src/cairo-array.c index 2b1cf9d6..a37ea9af 100644 --- a/src/cairo-array.c +++ b/src/cairo-array.c @@ -132,3 +132,142 @@ _cairo_array_num_elements (cairo_array_t *array) { return array->num_elements; } + +/* cairo_user_data_array_t */ + +typedef struct { + const cairo_user_data_key_t *key; + void *user_data; + cairo_destroy_func_t destroy; +} cairo_user_data_slot_t; + +/** + * _cairo_user_data_array_init: + * @array: a #cairo_user_data_array_t + * + * Initializes a #cairo_user_data_array_t structure for future + * use. After initialization, the array has no keys. Call + * _cairo_user_data_array_destroy() to free any allocated memory + * when done using the array. + **/ +void +_cairo_user_data_array_init (cairo_user_data_array_t *array) +{ + _cairo_array_init (array, sizeof (cairo_user_data_slot_t)); +} + +/** + * _cairo_user_data_array_destroy: + * @array: a #cairo_user_data_array_t + * + * Destroys all current keys in the user data array and deallocates + * any memory allocated for the array itself. + **/ +void +_cairo_user_data_array_destroy (cairo_user_data_array_t *array) +{ + int i, num_slots; + cairo_user_data_slot_t *slots; + + num_slots = array->num_elements; + slots = (cairo_user_data_slot_t *) array->elements; + for (i = 0; i < num_slots; i++) { + if (slots[i].user_data != NULL && slots[i].destroy != NULL) + slots[i].destroy (slots[i].user_data); + } + + _cairo_array_fini (array); +} + +/** + * _cairo_user_data_array_get_data: + * @array: a #cairo_user_data_array_t + * @key: the address of the #cairo_user_data_key_t the user data was + * attached to + * + * Returns user data previously attached using the specified + * key. If no user data has been attached with the given key this + * function returns %NULL. + * + * Return value: the user data previously attached or %NULL. + **/ +void * +_cairo_user_data_array_get_data (cairo_user_data_array_t *array, + const cairo_user_data_key_t *key) +{ + int i, num_slots; + cairo_user_data_slot_t *slots; + + num_slots = array->num_elements; + slots = (cairo_user_data_slot_t *) array->elements; + for (i = 0; i < num_slots; i++) { + if (slots[i].key == key) + return slots[i].user_data; + } + + return NULL; +} + +/** + * _cairo_user_data_array_set_data: + * @array: a #cairo_user_data_array_t + * @key: the address of a #cairo_user_data_key_t to attach the user data to + * @user_data: the user data to attach + * @destroy: a #cairo_destroy_func_t which will be called when the + * user data array is destroyed or when new user data is attached using the + * same key. + * + * Attaches user data to a user data array. To remove user data, + * call this function with the key that was used to set it and %NULL + * for @data. + * + * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a + * slot could not be allocated for the user data. + **/ +cairo_status_t +_cairo_user_data_array_set_data (cairo_user_data_array_t *array, + const cairo_user_data_key_t *key, + void *user_data, + cairo_destroy_func_t destroy) +{ + int i, num_slots; + cairo_user_data_slot_t *slots, *s; + + s = NULL; + num_slots = array->num_elements; + slots = (cairo_user_data_slot_t *) array->elements; + for (i = 0; i < num_slots; i++) { + if (slots[i].key == key) { + if (slots[i].user_data != NULL && slots[i].destroy != NULL) + slots[i].destroy (slots[i].user_data); + s = &slots[i]; + break; + } + if (user_data && slots[i].user_data == NULL) { + s = &slots[i]; /* Have to keep searching for an exact match */ + } + } + + if (user_data == NULL) { + if (s != NULL) { + s->key = NULL; + s->user_data = NULL; + s->destroy = NULL; + } + + return CAIRO_STATUS_SUCCESS; + + } else { + if (s == NULL) + s = _cairo_array_append (array, NULL, 1); + if (s == NULL) + return CAIRO_STATUS_NO_MEMORY; + + s->key = key; + s->user_data = user_data; + s->destroy = destroy; + } + + return CAIRO_STATUS_SUCCESS; +} + |