diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h index 3951793c1..cef2d753a 100644 --- a/src/cairo-image-surface-private.h +++ b/src/cairo-image-surface-private.h @@ -50,6 +50,19 @@ struct _cairo_image_surface { pixman_image_t *pixman_image; const cairo_compositor_t *compositor; + + /* Parenting is tricky wrt lifetime tracking... + * + * One use for tracking the parent of an image surface is for + * create_similar_image() where we wish to create a device specific + * surface but return an image surface to the user. In such a case, + * the image may be owned by the device specific surface, its parent, + * but the user lifetime tracking is then performed on the image. So + * when the image is then finalized we call cairo_surface_destroy() + * on the parent. However, for normal usage where the lifetime tracking + * is done on the parent surface, we need to be careful to unhook + * the image->parent pointer before finalizing the image. + */ cairo_surface_t *parent; pixman_format_code_t pixman_format; diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 66f024c56..982bf45d0 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -813,6 +813,11 @@ _cairo_image_surface_finish (void *abstract_surface) surface->data = NULL; } + if (surface->parent) { + cairo_surface_destroy (surface->parent); + surface->parent = NULL; + } + return CAIRO_STATUS_SUCCESS; } diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c index 1b5d47edb..ac37cbf00 100644 --- a/src/win32/cairo-win32-display-surface.c +++ b/src/win32/cairo-win32-display-surface.c @@ -405,8 +405,12 @@ _cairo_win32_display_surface_finish (void *abstract_surface) { cairo_win32_display_surface_t *surface = abstract_surface; - if (surface->image) + if (surface->image) { + /* Unhook ourselves first to avoid the double-unref from the image */ + surface->image->parent = NULL; + cairo_surface_finish (surface->image); cairo_surface_destroy (surface->image); + } /* If we created the Bitmap and DC, destroy them */ if (surface->bitmap) {