michael@0: Author: Jeff Muizelaar michael@0: diff --git a/src/cairo-surface.c b/src/cairo-surface.c michael@0: index 8278694..12f6242 100644 michael@0: --- a/src/cairo-surface.c michael@0: +++ b/src/cairo-surface.c michael@0: @@ -1530,6 +1530,70 @@ _cairo_recording_surface_clone_similar (cairo_surface_t *surface, michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: +struct acquire_source_image_data michael@0: +{ michael@0: + cairo_surface_t *src; michael@0: + cairo_image_surface_t *image; michael@0: + void *image_extra; michael@0: +}; michael@0: + michael@0: +static void michael@0: +_wrap_release_source_image (void *data) michael@0: +{ michael@0: + struct acquire_source_image_data *acquire_data = data; michael@0: + _cairo_surface_release_source_image (acquire_data->src, michael@0: + acquire_data->image, michael@0: + acquire_data->image_extra); michael@0: + free(data); michael@0: +} michael@0: + michael@0: +static cairo_status_t michael@0: +_wrap_image (cairo_surface_t *src, michael@0: + cairo_image_surface_t *image, michael@0: + void *image_extra, michael@0: + cairo_image_surface_t **out) michael@0: +{ michael@0: + static cairo_user_data_key_t wrap_image_key; michael@0: + cairo_image_surface_t *surface; michael@0: + cairo_status_t status; michael@0: + michael@0: + struct acquire_source_image_data *data = malloc (sizeof (*data)); michael@0: + if (unlikely (data == NULL)) michael@0: + return _cairo_error (CAIRO_STATUS_NO_MEMORY); michael@0: + data->src = src; michael@0: + data->image = image; michael@0: + data->image_extra = image_extra; michael@0: + michael@0: + surface = (cairo_image_surface_t *) michael@0: + _cairo_image_surface_create_with_pixman_format (image->data, michael@0: + image->pixman_format, michael@0: + image->width, michael@0: + image->height, michael@0: + image->stride); michael@0: + status = surface->base.status; michael@0: + if (status) { michael@0: + free (data); michael@0: + return status; michael@0: + } michael@0: + michael@0: + status = _cairo_user_data_array_set_data (&surface->base.user_data, michael@0: + &wrap_image_key, michael@0: + data, michael@0: + _wrap_release_source_image); michael@0: + if (status) { michael@0: + cairo_surface_destroy (&surface->base); michael@0: + free (data); michael@0: + return status; michael@0: + } michael@0: + michael@0: + pixman_image_set_component_alpha ( michael@0: + surface->pixman_image, michael@0: + pixman_image_get_component_alpha (surface->pixman_image)); michael@0: + michael@0: + *out = surface; michael@0: + return CAIRO_STATUS_SUCCESS; michael@0: +} michael@0: + michael@0: /** michael@0: * _cairo_surface_clone_similar: michael@0: * @surface: a #cairo_surface_t michael@0: @@ -1606,15 +1670,19 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, michael@0: /* If we failed, try again with an image surface */ michael@0: status = _cairo_surface_acquire_source_image (src, &image, &image_extra); michael@0: if (status == CAIRO_STATUS_SUCCESS) { michael@0: - status = michael@0: - surface->backend->clone_similar (surface, &image->base, michael@0: - src_x, src_y, michael@0: - width, height, michael@0: - clone_offset_x, michael@0: - clone_offset_y, michael@0: - clone_out); michael@0: - michael@0: - _cairo_surface_release_source_image (src, image, image_extra); michael@0: + status = _wrap_image(src, image, image_extra, &image); michael@0: + if (status != CAIRO_STATUS_SUCCESS) { michael@0: + _cairo_surface_release_source_image (src, image, image_extra); michael@0: + } else { michael@0: + status = michael@0: + surface->backend->clone_similar (surface, &image->base, michael@0: + src_x, src_y, michael@0: + width, height, michael@0: + clone_offset_x, michael@0: + clone_offset_y, michael@0: + clone_out); michael@0: + cairo_surface_destroy(&image->base); michael@0: + } michael@0: } michael@0: } michael@0: }