[cairo-commit]
cairo/src cairo-array.c, 1.2, 1.3 cairo-atsui-font.c,
1.7, 1.8 cairo-font.c, 1.42, 1.43 cairo-ft-font.c, 1.54,
1.55 cairo-gstate.c, 1.107, 1.108 cairo-pdf-surface.c, 1.27,
1.28 cairo-surface.c, 1.54, 1.55 cairo-win32-font.c, 1.15,
1.16 cairo.h, 1.95, 1.96 cairoint.h, 1.123, 1.124
Owen Taylor
commit at pdx.freedesktop.org
Fri Apr 8 13:14:19 PDT 2005
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv9556/src
Modified Files:
cairo-array.c cairo-atsui-font.c cairo-font.c cairo-ft-font.c
cairo-gstate.c cairo-pdf-surface.c cairo-surface.c
cairo-win32-font.c cairo.h cairoint.h
Log Message:
2005-04-08 Owen Taylor <otaylor at redhat.com>
* 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.
* src/cairo-font.c (cairo_font_face_destroy,
(cairo_scaled_font_destroy, _cairo_unscaled_font_destroy):
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.
* src/cairo-ft-font.c (_cairo_ft_unscaled_font_destroy,
_ft_font_face_destroy): 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.
* src/cairo-ft-font.c (cairo_ft_font_face_create_for_ft_face):
Update the docs to describe how to figure out when the FT_Face
can be freed.
* src/cairo-ft-font.c: Fix refcount leaks when creating fonts.
* src/cairo-pdf-surface.c (cairo_pdf_ft_font_create): Remove
excess call to _cairo_unscaled_font_reference().
* src/cairo-gstate.c (_cairo_gstate_set_font_face): Remove
stray initialization of font matrix to the identity.
* src/cairo-array.c (_cairo_user_data_array_set_data) 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.
* src/cairo-array.c (_cairo_user_data_array_set_data):
Don't append an element when user_data is NULL.
Index: cairo-array.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-array.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cairo-array.c 17 Jan 2005 17:40:01 -0000 1.2
+++ cairo-array.c 8 Apr 2005 20:14:17 -0000 1.3
@@ -132,3 +132,142 @@
{
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;
+}
+
Index: cairo-atsui-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-atsui-font.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cairo-atsui-font.c 7 Apr 2005 17:01:49 -0000 1.7
+++ cairo-atsui-font.c 8 Apr 2005 20:14:17 -0000 1.8
@@ -214,8 +214,6 @@
ATSUDisposeStyle(font->style);
if (font->unscaled_style)
ATSUDisposeStyle(font->unscaled_style);
-
- free(font);
}
Index: cairo-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-font.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- cairo-font.c 7 Apr 2005 20:29:32 -0000 1.42
+++ cairo-font.c 8 Apr 2005 20:14:17 -0000 1.43
@@ -47,6 +47,8 @@
{
font_face->refcount = 1;
font_face->backend = backend;
+
+ _cairo_user_data_array_init (&font_face->user_data);
}
/**
@@ -73,11 +75,70 @@
**/
void
cairo_font_face_destroy (cairo_font_face_t *font_face)
-{
+{
+ cairo_user_data_array_t user_data_copy;
+
if (--(font_face->refcount) > 0)
return;
font_face->backend->destroy (font_face);
+
+ /* We allow resurrection to deal with some memory management for the
+ * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
+ * need to effectively mutually reference each other
+ */
+ if (font_face->refcount > 0)
+ return;
+
+ _cairo_user_data_array_destroy (&font_face->user_data);
+
+ free (font_face);
+}
+
+/**
+ * cairo_font_face_get_user_data:
+ * @font_face: a #cairo_font_face_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @font_face 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_font_face_get_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key)
+{
+ return _cairo_user_data_array_get_data (&font_face->user_data,
+ key);
+}
+
+/**
+ * cairo_font_face_set_user_data:
+ * @font_face: a #cairo_font_face_t
+ * @key: the address of a #cairo_user_data_key_t to attach the user data to
+ * @user_data: the user data to attach to the font face
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * font face is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @font_face. To remove user data from a font face,
+ * 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_font_face_set_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key,
+ void *user_data,
+ cairo_destroy_func_t destroy)
+{
+ return _cairo_user_data_array_set_data (&font_face->user_data,
+ key, user_data, destroy);
}
/* cairo_simple_font_face_t - simple family/slant/weight font faces used for
@@ -799,6 +860,8 @@
return;
unscaled_font->backend->destroy (unscaled_font);
+
+ free (unscaled_font);
}
@@ -852,6 +915,8 @@
}
scaled_font->backend->destroy (scaled_font);
+
+ free (scaled_font);
}
/**
Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- cairo-ft-font.c 7 Apr 2005 18:04:00 -0000 1.54
+++ cairo-ft-font.c 8 Apr 2005 20:14:17 -0000 1.55
@@ -482,7 +482,13 @@
{
ft_unscaled_font_t *unscaled = abstract_font;
- if (!unscaled->from_face) {
+ if (unscaled->from_face) {
+ /* See comments in _ft_font_face_destroy about the "zombie" state
+ * for a _ft_font_face.
+ */
+ if (unscaled->faces && !unscaled->faces->unscaled)
+ cairo_font_face_destroy (&unscaled->faces->base);
+ } else {
cairo_cache_t *cache;
cairo_ft_cache_key_t key;
@@ -496,18 +502,13 @@
_cairo_cache_remove (cache, &key);
_unlock_global_ft_cache ();
+
+ if (unscaled->filename)
+ free (unscaled->filename);
+
+ if (unscaled->face)
+ FT_Done_Face (unscaled->face);
}
-
- if (unscaled == NULL)
- return;
-
- if (!unscaled->from_face && unscaled->face)
- FT_Done_Face (unscaled->face);
-
- if (unscaled->filename)
- free (unscaled->filename);
-
- free (unscaled);
}
static cairo_status_t
@@ -830,8 +831,6 @@
return;
_cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
-
- free (scaled_font);
}
static void
@@ -1332,20 +1331,47 @@
ft_font_face_t *tmp_face = NULL;
ft_font_face_t *last_face = NULL;
- /* Remove face from linked list */
- for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) {
- if (tmp_face == font_face) {
- if (last_face)
- last_face->next_face = tmp_face->next_face;
- else
- font_face->unscaled->faces = tmp_face->next_face;
- }
+ /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
+ * we have a special "zombie" state for the face when the unscaled font
+ * is still alive but there are no public references to the font face.
+ *
+ * We go from:
+ *
+ * font_face ------> unscaled
+ * <-....weak....../
+ *
+ * To:
+ *
+ * font_face <------- unscaled
+ */
- last_face = tmp_face;
+ if (font_face->unscaled &&
+ font_face->unscaled->from_face &&
+ font_face->unscaled->base.refcount > 1) {
+ cairo_font_face_reference (&font_face->base);
+
+ _cairo_unscaled_font_destroy (&font_face->unscaled->base);
+ font_face->unscaled = NULL;
+
+ return;
}
+
+ if (font_face->unscaled) {
+ /* Remove face from linked list */
+ for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) {
+ if (tmp_face == font_face) {
+ if (last_face)
+ last_face->next_face = tmp_face->next_face;
+ else
+ font_face->unscaled->faces = tmp_face->next_face;
+ }
+
+ last_face = tmp_face;
+ }
- _cairo_unscaled_font_destroy (&font_face->unscaled->base);
- free (font_face);
+ _cairo_unscaled_font_destroy (&font_face->unscaled->base);
+ font_face->unscaled = NULL;
+ }
}
static cairo_status_t
@@ -1426,21 +1452,26 @@
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
ft_unscaled_font_t *unscaled;
+ cairo_font_face_t *font_face;
unscaled = _ft_unscaled_font_get_for_pattern (pattern);
if (unscaled == NULL)
return NULL;
- return _ft_font_face_create (unscaled, _get_load_flags (pattern));
+ font_face = _ft_font_face_create (unscaled, _get_load_flags (pattern));
+ _cairo_unscaled_font_destroy (&unscaled->base);
+
+ return font_face;
}
/**
* cairo_ft_font_create_for_ft_face:
* @face: A FreeType face object, already opened. This must
- * be kept around until the font object's refcount drops to
- * zero and it is freed. The font object can be kept alive by
- * internal caching, so it's safest to keep the face object
- * around forever.
+ * be kept around until the face's refcount drops to
+ * zero and it is freed. Since the face may be referenced
+ * internally to Cairo, the best way to determine when it
+ * is safe to free the face is to pass a
+ * #cairo_destroy_func_t to cairo_font_face_set_user_data()
* @load_flags: The flags to pass to FT_Load_Glyph when loading
* glyphs from the font. These flags control aspects of
* rendering such as hinting and antialiasing. See the FreeType
@@ -1460,12 +1491,16 @@
int load_flags)
{
ft_unscaled_font_t *unscaled;
+ cairo_font_face_t *font_face;
unscaled = _ft_unscaled_font_create_from_face (face);
if (unscaled == NULL)
return NULL;
- return _ft_font_face_create (unscaled, load_flags);
+ font_face = _ft_font_face_create (unscaled, load_flags);
+ _cairo_unscaled_font_destroy (&unscaled->base);
+
+ return font_face;
}
/**
Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.107
retrieving revision 1.108
diff -u -d -r1.107 -r1.108
--- cairo-gstate.c 8 Apr 2005 17:03:17 -0000 1.107
+++ cairo-gstate.c 8 Apr 2005 20:14:17 -0000 1.108
@@ -2359,7 +2359,6 @@
cairo_font_face_reference (gstate->font_face);
}
- cairo_matrix_init_identity (&gstate->font_matrix);
_cairo_gstate_unset_font (gstate);
return CAIRO_STATUS_SUCCESS;
Index: cairo-pdf-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pdf-surface.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- cairo-pdf-surface.c 7 Apr 2005 21:25:00 -0000 1.27
+++ cairo-pdf-surface.c 8 Apr 2005 20:14:17 -0000 1.28
@@ -324,8 +324,6 @@
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
- font->base.unscaled_font = unscaled_font;
- _cairo_unscaled_font_reference (unscaled_font);
font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- cairo-surface.c 7 Apr 2005 21:25:00 -0000 1.54
+++ cairo-surface.c 8 Apr 2005 20:14:17 -0000 1.55
@@ -38,12 +38,6 @@
#include "cairoint.h"
-typedef struct {
- const cairo_user_data_key_t *key;
- void *user_data;
- cairo_destroy_func_t destroy;
-} cairo_user_data_slot_t;
-
void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend)
@@ -53,8 +47,7 @@
surface->ref_count = 1;
surface->finished = FALSE;
- _cairo_array_init (&surface->user_data_slots,
- sizeof (cairo_user_data_slot_t));
+ _cairo_user_data_array_init (&surface->user_data);
cairo_matrix_init_identity (&surface->matrix);
surface->filter = CAIRO_FILTER_NEAREST;
@@ -132,22 +125,6 @@
surface->ref_count++;
}
-static void
-_destroy_user_data (cairo_surface_t *surface)
-{
- int i, num_slots;
- cairo_user_data_slot_t *slots;
-
- num_slots = surface->user_data_slots.num_elements;
- slots = (cairo_user_data_slot_t *) surface->user_data_slots.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 (&surface->user_data_slots);
-}
-
void
cairo_surface_destroy (cairo_surface_t *surface)
{
@@ -160,7 +137,7 @@
cairo_surface_finish (surface);
- _destroy_user_data (surface);
+ _cairo_user_data_array_destroy (&surface->user_data);
free (surface);
}
@@ -216,17 +193,8 @@
cairo_surface_get_user_data (cairo_surface_t *surface,
const cairo_user_data_key_t *key)
{
- int i, num_slots;
- cairo_user_data_slot_t *slots;
-
- num_slots = surface->user_data_slots.num_elements;
- slots = (cairo_user_data_slot_t *) surface->user_data_slots.elements;
- for (i = 0; i < num_slots; i++) {
- if (slots[i].key == key)
- return slots[i].user_data;
- }
-
- return NULL;
+ return _cairo_user_data_array_get_data (&surface->user_data,
+ key);
}
/**
@@ -251,35 +219,8 @@
void *user_data,
cairo_destroy_func_t destroy)
{
- int i, num_slots;
- cairo_user_data_slot_t *slots, *s;
-
- s = NULL;
- num_slots = surface->user_data_slots.num_elements;
- slots = (cairo_user_data_slot_t *) surface->user_data_slots.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 (slots[i].user_data == NULL) {
- s = &slots[i];
- break;
- }
- }
-
- if (s == NULL)
- s = _cairo_array_append (&surface->user_data_slots, 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;
+ return _cairo_user_data_array_set_data (&surface->user_data,
+ key, user_data, destroy);
}
/**
Index: cairo-win32-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-win32-font.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- cairo-win32-font.c 7 Apr 2005 19:56:43 -0000 1.15
+++ cairo-win32-font.c 8 Apr 2005 20:14:17 -0000 1.16
@@ -470,8 +470,6 @@
if (scaled_font->unscaled_hfont)
DeleteObject (scaled_font->unscaled_hfont);
-
- free (scaled_font);
}
static void
@@ -1130,7 +1128,6 @@
static void
_cairo_win32_font_face_destroy (void *abstract_face)
{
- free (abstract_face);
}
static cairo_status_t
Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- cairo.h 8 Apr 2005 17:03:17 -0000 1.95
+++ cairo.h 8 Apr 2005 20:14:17 -0000 1.96
@@ -102,6 +102,28 @@
typedef struct _cairo_pattern cairo_pattern_t;
+/**
+ * cairo_destroy_func_t
+ *
+ * #cairo_destroy_func_t the type of function which is called when a
+ * data element is destroyed. It is passed the pointer to the data
+ * element and should free any memory and resources allocated for it.
+ */
+typedef void (*cairo_destroy_func_t) (void *data);
+
+/**
+ * cairo_user_data_key_t
+ *
+ * #cairo_user_data_key_t is used for attaching user data to cairo
+ * data structures. The actual contents of the struct is never used,
+ * and there is no need to initialize the object; only the unique
+ * address of a #cairo_data_key_t object is used. Typically, you
+ * would just use the address of a static #cairo_data_key_t object.
+ */
+typedef struct _cairo_user_data_key {
+ int unused;
+} cairo_user_data_key_t;
+
typedef enum cairo_status {
CAIRO_STATUS_SUCCESS = 0,
CAIRO_STATUS_NO_MEMORY,
@@ -622,6 +644,15 @@
void
cairo_font_face_destroy (cairo_font_face_t *font_face);
+void *
+cairo_font_face_get_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key);
+
+cairo_status_t
+cairo_font_face_set_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key,
+ void *user_data,
+ cairo_destroy_func_t destroy);
/* Portable interface to general font features. */
@@ -850,15 +881,6 @@
const char *
cairo_status_string (cairo_t *cr);
-/**
- * cairo_destroy_func_t
- *
- * #cairo_destroy_func_t the type of function which is called when a
- * data element is destroyed. It is passed the pointer to the data
- * element and should free any memory and resources allocated for it.
- */
-typedef void (*cairo_destroy_func_t) (void *data);
-
/* Surface manipulation */
/* XXX: I want to remove this function, (replace with
@@ -908,20 +930,6 @@
cairo_filter_t
cairo_surface_get_filter (cairo_surface_t *surface);
-
-/**
- * cairo_user_data_key_t
- *
- * #cairo_user_data_key_t is used for attaching user data to cairo
- * data structures. The actual contents of the struct is never used,
- * and there is no need to initialize the object; only the unique
- * address of a #cairo_data_key_t object is used. Typically, you
- * would just use the address of a static #cairo_data_key_t object.
- */
-typedef struct _cairo_user_data_key {
- int unused;
-} cairo_user_data_key_t;
-
void *
cairo_surface_get_user_data (cairo_surface_t *surface,
const cairo_user_data_key_t *key);
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.123
retrieving revision 1.124
diff -u -d -r1.123 -r1.124
--- cairoint.h 8 Apr 2005 17:03:17 -0000 1.123
+++ cairoint.h 8 Apr 2005 20:14:17 -0000 1.124
@@ -279,6 +279,24 @@
cairo_private int
_cairo_array_num_elements (cairo_array_t *array);
+typedef cairo_array_t cairo_user_data_array_t;
+
+cairo_private void
+_cairo_user_data_array_init (cairo_user_data_array_t *array);
+
+cairo_private void
+_cairo_user_data_array_destroy (cairo_user_data_array_t *array);
+
+cairo_private void *
+_cairo_user_data_array_get_data (cairo_user_data_array_t *array,
+ const cairo_user_data_key_t *key);
+
+cairo_private 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);
+
/* cairo_cache.c structures and functions */
typedef struct _cairo_cache_backend {
@@ -407,6 +425,7 @@
struct _cairo_font_face {
int refcount;
+ cairo_user_data_array_t user_data;
const cairo_font_face_backend_t *backend;
};
@@ -512,6 +531,9 @@
};
struct _cairo_font_face_backend {
+ /* The destroy() function is allowed to resurrect the font face
+ * by re-referencing. This is needed for the FreeType backend.
+ */
void (*destroy) (void *font_face);
cairo_status_t (*create_font) (void *font_face,
cairo_matrix_t *font_matrix,
@@ -656,7 +678,7 @@
unsigned int ref_count;
cairo_bool_t finished;
- cairo_array_t user_data_slots;
+ cairo_user_data_array_t user_data;
cairo_matrix_t matrix;
cairo_filter_t filter;
More information about the cairo-commit
mailing list