[cairo-commit] 4 commits - src/cairoint.h src/cairo-user-font.c src/cairo-xlib-display.c src/cairo-xlib-private.h src/cairo-xlib-screen.c src/cairo-xlib-surface.c src/cairo-xlib-surface-private.h test/cairo-test.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Sep 2 03:22:19 PDT 2008


 src/cairo-user-font.c            |   10 ++-
 src/cairo-xlib-display.c         |  105 ++++++++++++++-------------------------
 src/cairo-xlib-private.h         |   19 ++++---
 src/cairo-xlib-screen.c          |   14 +----
 src/cairo-xlib-surface-private.h |    2 
 src/cairo-xlib-surface.c         |   76 +++++++++++++++++++---------
 src/cairoint.h                   |   10 +++
 test/cairo-test.c                |    5 +
 8 files changed, 133 insertions(+), 108 deletions(-)

New commits:
commit 7b2e8035f253e4667ebdb285d7b49aaece88f3b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 2 10:54:13 2008 +0100

    [cairo-test] Fixup a few memleaks on failure.
    
    Free the test image before jumping to UNWIND_CAIRO.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index c0e59bf..6c04f8c 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -689,6 +689,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	if (cairo_surface_status (test_image)) {
 	    cairo_test_log (ctx, "Error: Failed to extract image: %s\n",
 			    cairo_status_to_string (cairo_surface_status (test_image)));
+	    cairo_surface_destroy (test_image);
 	    ret = CAIRO_TEST_FAILURE;
 	    goto UNWIND_CAIRO;
 	}
@@ -713,6 +714,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	    if (cairo_test_files_equal (test_filename, pass_filename)) {
 		/* identical output as last known PASS */
 		cairo_test_log (ctx, "Vector surface matches last pass.\n");
+		cairo_surface_destroy (test_image);
 		ret = CAIRO_TEST_SUCCESS;
 		goto UNWIND_CAIRO;
 	    }
@@ -720,6 +722,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 		/* identical output as last known FAIL, fail */
 		cairo_test_log (ctx, "Vector surface matches last fail.\n");
 		have_result = TRUE; /* presume these were kept around as well */
+		cairo_surface_destroy (test_image);
 		ret = CAIRO_TEST_FAILURE;
 		goto UNWIND_CAIRO;
 	    }
@@ -728,6 +731,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	if (ref_name == NULL) {
 	    cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
 			    base_name);
+	    cairo_surface_destroy (test_image);
 	    ret = CAIRO_TEST_FAILURE;
 	    goto UNWIND_CAIRO;
 	}
@@ -776,6 +780,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	    cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
 			    ref_name,
 			    cairo_status_to_string (cairo_surface_status (ref_image)));
+	    cairo_surface_destroy (ref_image);
 	    cairo_surface_destroy (test_image);
 	    ret = CAIRO_TEST_FAILURE;
 	    goto UNWIND_CAIRO;
commit a5d33bcbb43cd1738e45b803c1aa968aff55e7ab
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 2 10:28:17 2008 +0100

    [xlib] Keep a pointer to the cairo_xlib_display_t on the surface.
    
    Cleanup the code somewhat by passing cairo_xlib_display_t around
    internally as opposed to a Display and then having to lookup the
    corresponding cairo_xlib_display_t each time.
    
    [To get a cairo_xlib_display_t from a Display is a list traversal under
    mutex (though the element we're looking for is most likely at the start),
    but to get the Display is just a lockless pointer dereference.]

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index ff2e08e..5e6dba1 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -90,7 +90,7 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
 	_cairo_xlib_remove_close_display_hook_internal (display, hook);
 
 	CAIRO_MUTEX_UNLOCK (display->mutex);
-	hook->func (display->display, hook);
+	hook->func (display, hook);
 	CAIRO_MUTEX_LOCK (display->mutex);
     }
     display->closed = TRUE;
@@ -317,15 +317,10 @@ UNLOCK:
     return display;
 }
 
-cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *dpy, cairo_xlib_hook_t *hook)
+void
+_cairo_xlib_add_close_display_hook (cairo_xlib_display_t	*display,
+				    cairo_xlib_hook_t		*hook)
 {
-    cairo_xlib_display_t *display;
-
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return FALSE;
-
     CAIRO_MUTEX_LOCK (display->mutex);
     hook->prev = NULL;
     hook->next = display->close_display_hooks;
@@ -333,10 +328,6 @@ _cairo_xlib_add_close_display_hook (Display *dpy, cairo_xlib_hook_t *hook)
 	hook->next->prev = hook;
     display->close_display_hooks = hook;
     CAIRO_MUTEX_UNLOCK (display->mutex);
-
-    _cairo_xlib_display_destroy (display);
-
-    return TRUE;
 }
 
 /* display->mutex must be held */
@@ -357,20 +348,12 @@ _cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
 }
 
 void
-_cairo_xlib_remove_close_display_hook (Display *dpy,
-				       cairo_xlib_hook_t *hook)
+_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t	*display,
+				       cairo_xlib_hook_t	*hook)
 {
-    cairo_xlib_display_t *display;
-
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return;
-
     CAIRO_MUTEX_LOCK (display->mutex);
     _cairo_xlib_remove_close_display_hook_internal (display, hook);
     CAIRO_MUTEX_UNLOCK (display->mutex);
-
-    _cairo_xlib_display_destroy (display);
 }
 
 cairo_status_t
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index e962278..e381e58 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -53,7 +53,7 @@ typedef void (*cairo_xlib_notify_resource_func) (Display *, XID);
 
 struct _cairo_xlib_hook {
     cairo_xlib_hook_t *prev, *next; /* private */
-    void (*func) (Display *display, void *data);
+    void (*func) (cairo_xlib_display_t *display, void *data);
 };
 
 struct _cairo_xlib_display {
@@ -113,11 +113,11 @@ _cairo_xlib_display_reference (cairo_xlib_display_t *info);
 cairo_private void
 _cairo_xlib_display_destroy (cairo_xlib_display_t *info);
 
-cairo_private cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *display, cairo_xlib_hook_t *hook);
+cairo_private void
+_cairo_xlib_add_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook);
 
 cairo_private void
-_cairo_xlib_remove_close_display_hook (Display *display, cairo_xlib_hook_t *hook);
+_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook);
 
 cairo_private cairo_status_t
 _cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
@@ -136,7 +136,7 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t	*display,
 	                                cairo_format_t		 format);
 
 cairo_private cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (Display *display, Screen *screen);
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen);
 
 cairo_private cairo_xlib_screen_info_t *
 _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 83015a2..4a26eee 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -346,19 +346,14 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
 }
 
 cairo_xlib_screen_info_t *
-_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
+_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen)
 {
-    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *info = NULL, **prev;
 
-    display = _cairo_xlib_display_get (dpy);
-    if (display == NULL)
-	return NULL;
-
     CAIRO_MUTEX_LOCK (display->mutex);
     if (display->closed) {
 	CAIRO_MUTEX_UNLOCK (display->mutex);
-	goto DONE;
+	return NULL;
     }
 
     for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
@@ -394,7 +389,9 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
 			       sizeof (cairo_xlib_visual_info_t*));
 
 	    if (screen) {
+		Display *dpy = display->display;
 		int event_base, error_base;
+
 		info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
 			(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
 		_cairo_xlib_init_screen_font_options (dpy, info);
@@ -407,9 +404,6 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
 	}
     }
 
-DONE:
-    _cairo_xlib_display_destroy (display);
-
     return info;
 }
 
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index a16e8e4..e06fd97 100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -45,6 +45,7 @@ struct _cairo_xlib_surface {
     cairo_surface_t base;
 
     Display *dpy;
+    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *screen_info;
     cairo_xlib_hook_t close_display_hook;
 
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index e9ff65d..d6f4109 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -320,12 +320,14 @@ _cairo_xlib_surface_finish (void *abstract_surface)
     if (surface->screen_info != NULL)
 	_cairo_xlib_screen_info_destroy (surface->screen_info);
 
-    if (surface->dpy != NULL) {
-	_cairo_xlib_remove_close_display_hook (surface->dpy,
+    if (surface->display != NULL) {
+	_cairo_xlib_remove_close_display_hook (surface->display,
 					       &surface->close_display_hook);
-	surface->dpy = NULL;
+	_cairo_xlib_display_destroy (surface->display);
     }
 
+    surface->dpy = NULL;
+
     return status;
 }
 
@@ -2381,12 +2383,14 @@ _cairo_surface_is_xlib (cairo_surface_t *surface)
 
 /* callback from CloseDisplay */
 static void
-_cairo_xlib_surface_detach_display (Display *dpy, void *data)
+_cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data)
 {
     cairo_xlib_surface_t *surface = cairo_container_of (data,
 							cairo_xlib_surface_t,
 							close_display_hook);
+    Display *dpy;
 
+    dpy = surface->dpy;
     surface->dpy = NULL;
 
     if (surface->dst_picture != None) {
@@ -2422,6 +2426,7 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
 				     int			depth)
 {
     cairo_xlib_surface_t *surface;
+    cairo_xlib_display_t *display;
     cairo_xlib_screen_info_t *screen_info;
 
     CAIRO_MUTEX_INITIALIZE ();
@@ -2453,25 +2458,26 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     if (depth == 0)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
-    screen_info = _cairo_xlib_screen_info_get (dpy, screen);
-    if (screen_info == NULL)
+    display = _cairo_xlib_display_get (dpy);
+    if (display == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    screen_info = _cairo_xlib_screen_info_get (display, screen);
+    if (screen_info == NULL) {
+	_cairo_xlib_display_destroy (display);
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
 
     surface = malloc (sizeof (cairo_xlib_surface_t));
     if (surface == NULL) {
 	_cairo_xlib_screen_info_destroy (screen_info);
+	_cairo_xlib_display_destroy (display);
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     /* initialize and hook into the CloseDisplay callback */
     surface->close_display_hook.func = _cairo_xlib_surface_detach_display;
-    if (! _cairo_xlib_add_close_display_hook (dpy,
-					      &surface->close_display_hook))
-    {
-	free (surface);
-	_cairo_xlib_screen_info_destroy (screen_info);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
+    _cairo_xlib_add_close_display_hook (display, &surface->close_display_hook);
 
     if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
 	surface->render_major = -1;
@@ -2493,6 +2499,7 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
 			 _xrender_format_to_content (xrender_format));
 
     surface->dpy = dpy;
+    surface->display = display;
     surface->screen_info = screen_info;
 
     surface->gc = NULL;
@@ -3000,8 +3007,8 @@ typedef struct _cairo_xlib_surface_font_private {
 
 /* callback from CloseDisplay */
 static void
-_cairo_xlib_surface_remove_scaled_font (Display *dpy,
-	                                void    *data)
+_cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t	*display,
+	                                void			*data)
 {
     cairo_xlib_surface_font_private_t	*font_private;
     cairo_scaled_font_t			*scaled_font;
@@ -3019,8 +3026,10 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy,
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
     if (font_private != NULL) {
+	Display *dpy;
 	int i;
 
+	dpy = display->display;
 	for (i = 0; i < NUM_GLYPHSETS; i++) {
 	    cairo_xlib_font_glyphset_info_t *glyphset_info;
 
@@ -3049,19 +3058,19 @@ _cairo_xlib_surface_font_init (Display		    *dpy,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     font_private->scaled_font = scaled_font;
+    font_private->display = _cairo_xlib_display_get (dpy);
+    if (font_private->display == NULL) {
+	free (font_private);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     /* initialize and hook into the CloseDisplay callback */
     font_private->close_display_hook.func =
 	_cairo_xlib_surface_remove_scaled_font;
-    if (! _cairo_xlib_add_close_display_hook (dpy,
-					      &font_private->close_display_hook))
-    {
-	free (font_private);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
+    _cairo_xlib_add_close_display_hook (font_private->display,
+					&font_private->close_display_hook);
 
 
-    font_private->display = _cairo_xlib_display_get (dpy);
     for (i = 0; i < NUM_GLYPHSETS; i++) {
 	cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
 	switch (i) {
@@ -3092,7 +3101,7 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 	int i;
 
 	display = font_private->display;
-	_cairo_xlib_remove_close_display_hook (display->display,
+	_cairo_xlib_remove_close_display_hook (display,
 					       &font_private->close_display_hook);
 
 	for (i = 0; i < NUM_GLYPHSETS; i++) {
commit 939b836bfa95df759aca96936bb9a6d89d3130b8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 2 10:08:04 2008 +0100

    [xlib] Use an embedded doubly-linked list for the close display hooks.
    
    Kill the allocation and linear search of the close display list on remove,
    by embedding a list node into the parent structure.
    
    Original patch by Karl Tomlinson <karlt+ at karlt.net>, Mozilla Corporation.
    https://bugzilla.mozilla.org/show_bug.cgi?id=453199#c5

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 895258d..ff2e08e 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -29,6 +29,8 @@
  *
  * The Initial Developer of the Original Code is Chris Wilson.
  *
+ * Contributor(s):
+ *	Karl Tomlinson <karlt+ at karlt.net>, Mozilla Corporation
  */
 
 #include "cairoint.h"
@@ -65,10 +67,14 @@ struct _cairo_xlib_job {
 static cairo_xlib_display_t *_cairo_xlib_display_list;
 
 static void
+_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
+						cairo_xlib_hook_t *hook);
+
+static void
 _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
 {
     cairo_xlib_screen_info_t	    *screen;
-    cairo_xlib_hook_t		    *hooks, *list;
+    cairo_xlib_hook_t		    *hook;
 
     /* call all registered shutdown routines */
     CAIRO_MUTEX_LOCK (display->mutex);
@@ -76,28 +82,16 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
     for (screen = display->screens; screen != NULL; screen = screen->next)
 	_cairo_xlib_screen_info_close_display (screen);
 
-    hooks = display->close_display_hooks;
-    while (hooks != NULL) {
-	display->close_display_hooks = NULL;
-	CAIRO_MUTEX_UNLOCK (display->mutex);
-
-	list = hooks;
-	do {
-	    cairo_xlib_hook_t *hook = list;
-	    list = hook->next;
+    while (TRUE) {
+	hook = display->close_display_hooks;
+	if (hook == NULL)
+	    break;
 
-	    hook->func (display->display, hook->data);
-	} while (list != NULL);
+	_cairo_xlib_remove_close_display_hook_internal (display, hook);
 
+	CAIRO_MUTEX_UNLOCK (display->mutex);
+	hook->func (display->display, hook);
 	CAIRO_MUTEX_LOCK (display->mutex);
-	do {
-	    cairo_xlib_hook_t *hook = hooks;
-	    hooks = hook->next;
-
-	    _cairo_freelist_free (&display->hook_freelist, hook);
-	} while (hooks != NULL);
-
-	hooks = display->close_display_hooks;
     }
     display->closed = TRUE;
 
@@ -151,7 +145,6 @@ _cairo_xlib_display_destroy (cairo_xlib_display_t *display)
 	_cairo_freelist_free (&display->wq_freelist, job);
     }
     _cairo_freelist_fini (&display->wq_freelist);
-    _cairo_freelist_fini (&display->hook_freelist);
 
     CAIRO_MUTEX_FINI (display->mutex);
 
@@ -277,7 +270,6 @@ _cairo_xlib_display_get (Display *dpy)
     XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
 
     _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t));
-    _cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t));
 
     CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */
     CAIRO_MUTEX_INIT (display->mutex);
@@ -326,56 +318,56 @@ UNLOCK:
 }
 
 cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data)
+_cairo_xlib_add_close_display_hook (Display *dpy, cairo_xlib_hook_t *hook)
 {
     cairo_xlib_display_t *display;
-    cairo_xlib_hook_t *hook;
-    cairo_bool_t ret = FALSE;
 
     display = _cairo_xlib_display_get (dpy);
     if (display == NULL)
 	return FALSE;
 
     CAIRO_MUTEX_LOCK (display->mutex);
-    if (display->closed == FALSE) {
-	hook = _cairo_freelist_alloc (&display->hook_freelist);
-	if (hook != NULL) {
-	    hook->func = func;
-	    hook->data = data;
-
-	    hook->next = display->close_display_hooks;
-	    display->close_display_hooks = hook;
-	    ret = TRUE;
-	}
-    }
+    hook->prev = NULL;
+    hook->next = display->close_display_hooks;
+    if (hook->next != NULL)
+	hook->next->prev = hook;
+    display->close_display_hooks = hook;
     CAIRO_MUTEX_UNLOCK (display->mutex);
 
     _cairo_xlib_display_destroy (display);
 
-    return ret;
+    return TRUE;
+}
+
+/* display->mutex must be held */
+static void
+_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
+						cairo_xlib_hook_t *hook)
+{
+    if (display->close_display_hooks == hook)
+	display->close_display_hooks = hook->next;
+    else if (hook->prev != NULL)
+	hook->prev->next = hook->next;
+
+    if (hook->next != NULL)
+	hook->next->prev = hook->prev;
+
+    hook->prev = NULL;
+    hook->next = NULL;
 }
 
 void
-_cairo_xlib_remove_close_display_hooks (Display *dpy, const void *data)
+_cairo_xlib_remove_close_display_hook (Display *dpy,
+				       cairo_xlib_hook_t *hook)
 {
     cairo_xlib_display_t *display;
-    cairo_xlib_hook_t *hook, *next, **prev;
 
     display = _cairo_xlib_display_get (dpy);
     if (display == NULL)
 	return;
 
     CAIRO_MUTEX_LOCK (display->mutex);
-    prev = &display->close_display_hooks;
-    for (hook = display->close_display_hooks; hook != NULL; hook = next) {
-	next = hook->next;
-	if (hook->data == data) {
-	    *prev = hook->next;
-	    _cairo_freelist_free (&display->hook_freelist, hook);
-	    break;
-	}
-	prev = &hook->next;
-    }
+    _cairo_xlib_remove_close_display_hook_internal (display, hook);
     CAIRO_MUTEX_UNLOCK (display->mutex);
 
     _cairo_xlib_display_destroy (display);
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 61ce889..e962278 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -28,6 +28,10 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributors(s):
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ *	Karl Tomlinson <karlt+ at karlt.net>, Mozilla Corporation
  */
 
 #ifndef CAIRO_XLIB_PRIVATE_H
@@ -48,9 +52,8 @@ typedef void (*cairo_xlib_notify_func) (Display *, void *);
 typedef void (*cairo_xlib_notify_resource_func) (Display *, XID);
 
 struct _cairo_xlib_hook {
-    cairo_xlib_hook_t *next;
+    cairo_xlib_hook_t *prev, *next; /* private */
     void (*func) (Display *display, void *data);
-    void *data;
 };
 
 struct _cairo_xlib_display {
@@ -66,7 +69,6 @@ struct _cairo_xlib_display {
     cairo_xlib_job_t *workqueue;
     cairo_freelist_t wq_freelist;
 
-    cairo_freelist_t hook_freelist;
     cairo_xlib_hook_t *close_display_hooks;
     unsigned int buggy_repeat :1;
     unsigned int closed :1;
@@ -112,9 +114,10 @@ cairo_private void
 _cairo_xlib_display_destroy (cairo_xlib_display_t *info);
 
 cairo_private cairo_bool_t
-_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data);
+_cairo_xlib_add_close_display_hook (Display *display, cairo_xlib_hook_t *hook);
+
 cairo_private void
-_cairo_xlib_remove_close_display_hooks (Display *display, const void *data);
+_cairo_xlib_remove_close_display_hook (Display *display, cairo_xlib_hook_t *hook);
 
 cairo_private cairo_status_t
 _cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index d5df19c..a16e8e4 100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -46,6 +46,7 @@ struct _cairo_xlib_surface {
 
     Display *dpy;
     cairo_xlib_screen_info_t *screen_info;
+    cairo_xlib_hook_t close_display_hook;
 
     GC gc;
     Drawable drawable;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index e7116f3..e9ff65d 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -35,6 +35,8 @@
  * Contributor(s):
  *	Carl D. Worth <cworth at cworth.org>
  *	Behdad Esfahbod <behdad at behdad.org>
+ *	Chris Wilson <chris at chris-wilson.co.uk>
+ *	Karl Tomlinson <karlt+ at karlt.net>, Mozilla Corporation
  */
 
 #include "cairoint.h"
@@ -319,7 +321,8 @@ _cairo_xlib_surface_finish (void *abstract_surface)
 	_cairo_xlib_screen_info_destroy (surface->screen_info);
 
     if (surface->dpy != NULL) {
-	_cairo_xlib_remove_close_display_hooks (surface->dpy, surface);
+	_cairo_xlib_remove_close_display_hook (surface->dpy,
+					       &surface->close_display_hook);
 	surface->dpy = NULL;
     }
 
@@ -2376,10 +2379,13 @@ _cairo_surface_is_xlib (cairo_surface_t *surface)
     return surface->backend == &cairo_xlib_surface_backend;
 }
 
+/* callback from CloseDisplay */
 static void
 _cairo_xlib_surface_detach_display (Display *dpy, void *data)
 {
-    cairo_xlib_surface_t *surface = data;
+    cairo_xlib_surface_t *surface = cairo_container_of (data,
+							cairo_xlib_surface_t,
+							close_display_hook);
 
     surface->dpy = NULL;
 
@@ -2457,8 +2463,10 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
+    /* initialize and hook into the CloseDisplay callback */
+    surface->close_display_hook.func = _cairo_xlib_surface_detach_display;
     if (! _cairo_xlib_add_close_display_hook (dpy,
-	    _cairo_xlib_surface_detach_display, surface))
+					      &surface->close_display_hook))
     {
 	free (surface);
 	_cairo_xlib_screen_info_destroy (screen_info);
@@ -2984,16 +2992,24 @@ typedef struct _cairo_xlib_font_glyphset_info {
 } cairo_xlib_font_glyphset_info_t;
 
 typedef struct _cairo_xlib_surface_font_private {
+    cairo_scaled_font_t		    *scaled_font;
+    cairo_xlib_hook_t                close_display_hook;
     cairo_xlib_display_t	    *display;
     cairo_xlib_font_glyphset_info_t  glyphset_info[NUM_GLYPHSETS];
 } cairo_xlib_surface_font_private_t;
 
+/* callback from CloseDisplay */
 static void
 _cairo_xlib_surface_remove_scaled_font (Display *dpy,
 	                                void    *data)
 {
-    cairo_scaled_font_t *scaled_font = data;
     cairo_xlib_surface_font_private_t	*font_private;
+    cairo_scaled_font_t			*scaled_font;
+
+    font_private = cairo_container_of (data,
+				       cairo_xlib_surface_font_private_t,
+				       close_display_hook);
+    scaled_font = font_private->scaled_font;
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
     font_private  = scaled_font->surface_private;
@@ -3032,9 +3048,13 @@ _cairo_xlib_surface_font_init (Display		    *dpy,
     if (font_private == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
+    font_private->scaled_font = scaled_font;
+
+    /* initialize and hook into the CloseDisplay callback */
+    font_private->close_display_hook.func =
+	_cairo_xlib_surface_remove_scaled_font;
     if (! _cairo_xlib_add_close_display_hook (dpy,
-		                         _cairo_xlib_surface_remove_scaled_font,
-					 scaled_font))
+					      &font_private->close_display_hook))
     {
 	free (font_private);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -3072,7 +3092,8 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 	int i;
 
 	display = font_private->display;
-	_cairo_xlib_remove_close_display_hooks (display->display, scaled_font);
+	_cairo_xlib_remove_close_display_hook (display->display,
+					       &font_private->close_display_hook);
 
 	for (i = 0; i < NUM_GLYPHSETS; i++) {
 	    cairo_xlib_font_glyphset_info_t *glyphset_info;
diff --git a/src/cairoint.h b/src/cairoint.h
index e4c3369..6986546 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -119,6 +119,16 @@ _cairo_win32_tmpfile (void);
  */
 #define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_SLANT
 
+#ifdef __GNUC__
+#define cairo_container_of(ptr, type, member) ({ \
+    const typeof(((type *) 0)->member) *mptr__ = (ptr); \
+    (type *) ((char *) mptr__ - offsetof (type, member)); \
+})
+#else
+#define cairo_container_of(ptr, type, member) \
+    (type *)((char *) (ptr) - (char *) &((type *)0)->member)
+#endif
+
 
 /* Size in bytes of buffer to use off the stack per functions.
  * Mostly used by text functions.  For larger allocations, they'll
commit 38f779afcb84d48a1a146eec11a6db5c484d3578
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 2 09:12:44 2008 +0100

    [user-font] Propagate status return.
    
    An error return possible went unpropagated - fix that. Also whilst in the
    vicinity avoid the non-constant initialisation of the local variable
    before the antiquated compilers moan.

diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index ebac53b..f49943b 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -147,8 +147,11 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 	    cairo_box_t bbox;
 	    double x1, y1, x2, y2;
 	    double x_scale, y_scale;
-	    cairo_surface_t *null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
-	    cairo_surface_t *analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
+	    cairo_surface_t *null_surface;
+	    cairo_surface_t *analysis_surface;
+
+	    null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
+	    analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
 	    cairo_surface_destroy (null_surface);
 
 	    _cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
@@ -156,6 +159,9 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 	    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
 	    cairo_surface_destroy (analysis_surface);
 
+	    if (status)
+		return status;
+
 	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
 
 	    x_scale = scaled_font->extent_x_scale;


More information about the cairo-commit mailing list