[cairo] user_data and get_reference_count APIs

Vladimir Vukicevic vladimir at pobox.com
Wed Feb 21 15:42:45 PST 2007


----- "Carl Worth" <cworth at cworth.org> wrote:
> On Wed, 21 Feb 2007 22:34:23 +0000 (GMT), Vladimir Vukicevic wrote:
> > It adds user_data to the public objects that were missing them
> (cairo_t, cairo_pattern_t, cairo_scaled_font_t):
> >
> >   cairo_get_user_data
> >   cairo_set_user_data
> >
> >   cairo_scaled_font_get_user_data
> >   cairo_scaled_font_set_user_data
> >
> >   cairo_pattern_get_user_data
> >   cairo_pattern_set_user_data
> >
> > It also adds a get_reference_count method to all five of the public
> refcounted objects:
> >
> >   cairo_get_reference_count
> >   cairo_surface_get_reference_count
> >   cairo_font_face_get_reference_count
> >   cairo_scaled_font_get_reference_count
> >   cairo_pattern_get_reference_count
> >
> > How's this look?
> 
> The above looks pretty good to me.
> 
> With this in place, will mozilla have everything it needs from cairo
> 1.4 API-wise?

I believe so, yes.

> > [2 cairo-user-data.patch <application/octet-stream (base64)>]
> 
> This, on the other hand, doesn't look good at all. It's hard for me to
> review a base64-encoded attachment (or at least this one...I think
> others were actually working for me recently---maybe it's the
> content-type or disposition).

A large part of the constant base64-encoded patches is due to cairo's 
use of UTF8 in comments for the copyright symbol and other data (e.g. 
some math stuff I believe in one of the files).  I guess another part is 
that some mailers (like Zimbra, apparently) try to guess file type based 
on extension.

But let's try this with the copyright symbol lines removed and with an 
explicit .txt extension...  This also includes the change of 
CAIRO_REF_COUNT_INVALID to be 0 instead of ((unsigned int) -1); this 
should have no effect on users as that value was never exposed.

     - Vlad

-------------- next part --------------
diff --git a/src/cairo-font.c b/src/cairo-font.c
index a310542..1b62aed 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -1,0 +1,1 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
@@ -164,6 +165,23 @@ cairo_font_face_get_type (cairo_font_fac
 }
 
 /**
+ * cairo_font_face_get_reference_count:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Returns the current reference count of @font_face.
+ *
+ * Return value: the current reference count of @font_face.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
+{
+    return font_face->ref_count;
+}
+
+/**
  * cairo_font_face_status:
  * @font_face: a #cairo_font_face_t
  *
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index ae271f8..5060eff 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -34,6 +34,7 @@ const cairo_solid_pattern_t cairo_patter
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
       CAIRO_REF_COUNT_INVALID,		/* ref_count */
       CAIRO_STATUS_NO_MEMORY,	/* status */
+      { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., }, /* matrix */
       CAIRO_FILTER_DEFAULT,	/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
@@ -43,6 +44,7 @@ static const cairo_solid_pattern_t cairo
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
       CAIRO_REF_COUNT_INVALID,		/* ref_count */
       CAIRO_STATUS_NULL_POINTER,/* status */
+      { 0, 0, 0, NULL },		/* user_data */
       { 1., 0., 0., 1., 0., 0., }, /* matrix */
       CAIRO_FILTER_DEFAULT,	/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
@@ -84,6 +86,8 @@ _cairo_pattern_init (cairo_pattern_t *pa
     pattern->ref_count = 1;
     pattern->status    = CAIRO_STATUS_SUCCESS;
 
+    _cairo_user_data_array_init (&pattern->user_data);
+
     if (type == CAIRO_PATTERN_TYPE_SURFACE)
 	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
     else
@@ -165,6 +169,8 @@ _cairo_pattern_init_copy (cairo_pattern_
 void
 _cairo_pattern_fini (cairo_pattern_t *pattern)
 {
+    _cairo_user_data_array_fini (&pattern->user_data);
+
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
 	break;
@@ -572,6 +578,76 @@ cairo_pattern_destroy (cairo_pattern_t *
 }
 slim_hidden_def (cairo_pattern_destroy);
 
+/**
+ * cairo_pattern_get_reference_count:
+ * @pattern: a #cairo_pattern_t
+ *
+ * Returns the current reference count of @pattern.
+ *
+ * Return value: the current reference count of @pattern.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
+{
+    return pattern->ref_count;
+}
+
+/**
+ * cairo_pattern_get_user_data:
+ * @pattern: a #cairo_pattern_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @pattern 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.
+ *
+ * Since: 1.4
+ **/
+void *
+cairo_pattern_get_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key)
+{
+    return _cairo_user_data_array_get_data (&pattern->user_data,
+					    key);
+}
+
+/**
+ * cairo_pattern_set_user_data:
+ * @pattern: a #cairo_pattern_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 #cairo_pattern_t
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * #cairo_t is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @pattern.  To remove user data from a surface,
+ * 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.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_set_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key,
+			     void			 *user_data,
+			     cairo_destroy_func_t	  destroy)
+{
+    if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return _cairo_user_data_array_set_data (&pattern->user_data,
+					    key, user_data, destroy);
+}
+
 static void
 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
 			       double			 offset,
diff --git a/src/cairo-private.h b/src/cairo-private.h
index 7051f7e..24ab3c1 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -44,6 +44,8 @@ struct _cairo {
 
     cairo_status_t status;
 
+    cairo_user_data_array_t user_data;
+
     cairo_path_fixed_t path;
 
     cairo_gstate_t *gstate;
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 02af487..46ba571 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1,2 +1,2 @@
-/* $Id: cairo-scaled-font.c,v 1.12 2006-01-22 10:33:26 behdad Exp $
- *
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/*
@@ -75,6 +75,7 @@ static const cairo_scaled_font_t _cairo_
     { 0 },			/* hash_entry */
     CAIRO_STATUS_NO_MEMORY,	/* status */
     CAIRO_REF_COUNT_INVALID,	/* ref_count */
+    { 0, 0, 0, NULL },		/* user_data */
     NULL,			/* font_face */
     { 1., 0., 0., 1., 0, 0},	/* font_matrix */
     { 1., 0., 0., 1., 0, 0},	/* ctm */
@@ -353,6 +354,8 @@ _cairo_scaled_font_init (cairo_scaled_fo
 {
     scaled_font->ref_count = 1;
 
+    _cairo_user_data_array_init (&scaled_font->user_data);
+
     _cairo_scaled_font_init_key (scaled_font, font_face,
 				 font_matrix, ctm, options);
 
@@ -426,6 +429,7 @@ _cairo_scaled_font_fini (cairo_scaled_fo
 
     scaled_font->backend->fini (scaled_font);
 
+    _cairo_user_data_array_fini (&scaled_font->user_data);
 }
 
 /**
@@ -620,6 +624,76 @@ cairo_scaled_font_destroy (cairo_scaled_
 }
 slim_hidden_def (cairo_scaled_font_destroy);
 
+/**
+ * cairo_scaled_font_get_reference_count:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Returns the current reference count of @scaled_font.
+ *
+ * Return value: the current reference count of @scaled_font.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font)
+{
+    return scaled_font->ref_count;
+}
+
+/**
+ * cairo_scaled_font_get_user_data:
+ * @scaled_font: a #cairo_scaled_font_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @scaled_font 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.
+ *
+ * Since: 1.4
+ **/
+void *
+cairo_scaled_font_get_user_data (cairo_scaled_font_t	     *scaled_font,
+				 const cairo_user_data_key_t *key)
+{
+    return _cairo_user_data_array_get_data (&scaled_font->user_data,
+					    key);
+}
+
+/**
+ * cairo_scaled_font_set_user_data:
+ * @scaled_font: a #cairo_scaled_font_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 #cairo_scaled_font_t
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * #cairo_t is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @scaled_font.  To remove user data from a surface,
+ * 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.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_scaled_font_set_user_data (cairo_scaled_font_t	     *scaled_font,
+				 const cairo_user_data_key_t *key,
+				 void			     *user_data,
+				 cairo_destroy_func_t	      destroy)
+{
+    if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return _cairo_user_data_array_set_data (&scaled_font->user_data,
+					    key, user_data, destroy);
+}
+
 /* Public font API follows. */
 
 /**
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 3c9df99..e640fac 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -392,6 +392,23 @@ cairo_surface_destroy (cairo_surface_t *
 slim_hidden_def(cairo_surface_destroy);
 
 /**
+ * cairo_surface_get_reference_count:
+ * @surface: a #cairo_surface_t
+ *
+ * Returns the current reference count of @surface.
+ *
+ * Return value: the current reference count of @surface.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_surface_get_reference_count (cairo_surface_t *surface)
+{
+    return surface->ref_count;
+}
+
+/**
  * cairo_surface_finish:
  * @surface: the #cairo_surface_t to finish
  *
diff --git a/src/cairo.c b/src/cairo.c
index 2e522a6..5eda36e 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -47,6 +47,7 @@
 static const cairo_t cairo_nil = {
   CAIRO_REF_COUNT_INVALID,	/* ref_count */
   CAIRO_STATUS_NO_MEMORY,	/* status */
+  { 0, 0, 0, NULL },		/* user_data */
   { 				/* path */
     NULL, NULL,			   /* op_buf_head, op_buf_tail */
     NULL, NULL,			   /* arg_buf_head, arg_buf_tail */
@@ -195,6 +196,8 @@ cairo_create (cairo_surface_t *target)
 
     cr->status = CAIRO_STATUS_SUCCESS;
 
+    _cairo_user_data_array_init (&cr->user_data);
+
     _cairo_path_fixed_init (&cr->path);
 
     if (target == NULL) {
@@ -269,11 +272,83 @@ cairo_destroy (cairo_t *cr)
 
     _cairo_path_fixed_fini (&cr->path);
 
+    _cairo_user_data_array_fini (&cr->user_data);
+
     free (cr);
 }
 slim_hidden_def (cairo_destroy);
 
 /**
+ * cairo_get_user_data:
+ * @cr: a #cairo_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Return user data previously attached to @cr 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.
+ *
+ * Since: 1.4
+ **/
+void *
+cairo_get_user_data (cairo_t			 *cr,
+		     const cairo_user_data_key_t *key)
+{
+    return _cairo_user_data_array_get_data (&cr->user_data,
+					    key);
+}
+
+/**
+ * cairo_set_user_data:
+ * @cr: a #cairo_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 #cairo_t
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * #cairo_t is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @cr.  To remove user data from a surface,
+ * 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.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_set_user_data (cairo_t			 *cr,
+		     const cairo_user_data_key_t *key,
+		     void			 *user_data,
+		     cairo_destroy_func_t	 destroy)
+{
+    if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return _cairo_user_data_array_set_data (&cr->user_data,
+					    key, user_data, destroy);
+}
+
+/**
+ * cairo_get_reference_count:
+ * @cr: a #cairo_t
+ *
+ * Returns the current reference count of @cr.
+ *
+ * Return value: the current reference count of @cr.  If the
+ * object is a nil object, 0 will be returned.
+ *
+ * Since: 1.4
+ **/
+unsigned int
+cairo_get_reference_count (cairo_t *cr)
+{
+    return cr->ref_count;
+}
+
+/**
  * cairo_save:
  * @cr: a #cairo_t
  *
diff --git a/src/cairo.h b/src/cairo.h
index 2cb8e96..ba5ead6 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -276,6 +276,19 @@ cairo_reference (cairo_t *cr);
 cairo_public void
 cairo_destroy (cairo_t *cr);
 
+cairo_public unsigned int
+cairo_get_reference_count (cairo_t *cr);
+
+cairo_public void *
+cairo_get_user_data (cairo_t			 *cr,
+		     const cairo_user_data_key_t *key);
+
+cairo_public cairo_status_t
+cairo_set_user_data (cairo_t			 *cr,
+		     const cairo_user_data_key_t *key,
+		     void			 *user_data,
+		     cairo_destroy_func_t	  destroy);
+
 cairo_public void
 cairo_save (cairo_t *cr);
 
@@ -972,6 +985,9 @@ cairo_font_face_reference (cairo_font_fa
 cairo_public void
 cairo_font_face_destroy (cairo_font_face_t *font_face);
 
+cairo_public unsigned int
+cairo_font_face_get_reference_count (cairo_font_face_t *font_face);
+
 cairo_public cairo_status_t
 cairo_font_face_status (cairo_font_face_t *font_face);
 
@@ -1045,12 +1061,25 @@ cairo_scaled_font_reference (cairo_scale
 cairo_public void
 cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
 
+cairo_public unsigned int
+cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font);
+
 cairo_public cairo_status_t
 cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
 
 cairo_public cairo_font_type_t
 cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font);
 
+cairo_public void *
+cairo_scaled_font_get_user_data (cairo_scaled_font_t         *scaled_font,
+				 const cairo_user_data_key_t *key);
+
+cairo_public cairo_status_t
+cairo_scaled_font_set_user_data (cairo_scaled_font_t         *scaled_font,
+				 const cairo_user_data_key_t *key,
+				 void                        *user_data,
+				 cairo_destroy_func_t	      destroy);
+
 cairo_public void
 cairo_scaled_font_extents (cairo_scaled_font_t  *scaled_font,
 			   cairo_font_extents_t *extents);
@@ -1268,6 +1297,9 @@ cairo_surface_finish (cairo_surface_t *s
 cairo_public void
 cairo_surface_destroy (cairo_surface_t *surface);
 
+cairo_public unsigned int
+cairo_surface_get_reference_count (cairo_surface_t *surface);
+
 cairo_public cairo_status_t
 cairo_surface_status (cairo_surface_t *surface);
 
@@ -1489,9 +1521,22 @@ cairo_pattern_reference (cairo_pattern_t
 cairo_public void
 cairo_pattern_destroy (cairo_pattern_t *pattern);
 
+cairo_public unsigned int
+cairo_pattern_get_reference_count (cairo_pattern_t *pattern);
+
 cairo_public cairo_status_t
 cairo_pattern_status (cairo_pattern_t *pattern);
 
+cairo_public void *
+cairo_pattern_get_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key);
+
+cairo_public cairo_status_t
+cairo_pattern_set_user_data (cairo_pattern_t		 *pattern,
+			     const cairo_user_data_key_t *key,
+			     void			 *user_data,
+			     cairo_destroy_func_t	  destroy);
+
 /**
  * cairo_pattern_type_t
  * @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform)
diff --git a/src/cairoint.h b/src/cairoint.h
index 2c145e0..65b0123 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -241,7 +241,7 @@ do {					\
     assert (NOT_REACHED);		\
 } while (0)
 
-#define CAIRO_REF_COUNT_INVALID ((unsigned int) -1)
+#define CAIRO_REF_COUNT_INVALID (0)
 
 #include "cairo-wideint-private.h"
 
@@ -578,6 +578,7 @@ struct _cairo_scaled_font {
     /* useful bits for _cairo_scaled_font_nil */
     cairo_status_t status;
     unsigned int ref_count;
+    cairo_user_data_array_t user_data;
 
     /* hash key members */
     cairo_font_face_t *font_face; /* may be NULL */
@@ -1117,12 +1118,14 @@ typedef enum {
 #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
 
 struct _cairo_pattern {
-    cairo_pattern_type_t type;
-    unsigned int	 ref_count;
-    cairo_status_t       status;
-    cairo_matrix_t	 matrix;
-    cairo_filter_t	 filter;
-    cairo_extend_t	 extend;
+    cairo_pattern_type_t    type;
+    unsigned int	    ref_count;
+    cairo_status_t          status;
+    cairo_user_data_array_t user_data;
+
+    cairo_matrix_t	    matrix;
+    cairo_filter_t	    filter;
+    cairo_extend_t	    extend;
 };
 
 typedef struct _cairo_solid_pattern {



More information about the cairo mailing list