summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-02-01 16:31:49 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-02-01 16:36:03 +0000
commitc391093f40472c2300f38d0e5857858f85586b60 (patch)
treee64ce1e4f706860de65439821ed3659eb3b174c0
parent15830fdb1087f18dcd6351de1034a5025b8ed343 (diff)
image: Add a convenience function for creating an image from another's data
The GL backend would like to extract a rectangle from another surface and convert it to a different pixel format. The _cairo_image_surface_create_from_image() does that by returning a new image that has the contents of the specified rectangle in the source Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/cairo-image-surface-private.h7
-rw-r--r--src/cairo-image-surface.c55
2 files changed, 62 insertions, 0 deletions
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 6a159d8a..8ca694c5 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -226,6 +226,13 @@ cairo_private cairo_image_surface_t *
_cairo_image_surface_clone_subimage (cairo_surface_t *surface,
const cairo_rectangle_int_t *extents);
+/* Similar to clone; but allow format conversion */
+cairo_private cairo_image_surface_t *
+_cairo_image_surface_create_from_image (cairo_image_surface_t *other,
+ pixman_format_code_t format,
+ int x, int y, int width, int height,
+ int stride);
+
CAIRO_END_DECLS
#endif /* CAIRO_IMAGE_SURFACE_PRIVATE_H */
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 20a1c03e..49f6e189 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1088,6 +1088,61 @@ _cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface,
return clone;
}
+cairo_image_surface_t *
+_cairo_image_surface_create_from_image (cairo_image_surface_t *other,
+ pixman_format_code_t format,
+ int x, int y,
+ int width, int height, int stride)
+{
+ cairo_image_surface_t *surface;
+ cairo_status_t status;
+ pixman_image_t *image;
+ void *mem = NULL;
+
+ status = other->base.status;
+ if (unlikely (status))
+ goto cleanup;
+
+ if (stride) {
+ mem = _cairo_malloc_ab (height, stride);
+ if (unlikely (mem == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
+ }
+
+ image = pixman_image_create_bits (format, width, height, mem, stride);
+ if (unlikely (image == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup_mem;
+ }
+
+ surface = (cairo_image_surface_t *)
+ _cairo_image_surface_create_for_pixman_image (image, format);
+ if (unlikely (surface->base.status)) {
+ status = surface->base.status;
+ goto cleanup_image;
+ }
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ other->pixman_image, NULL, image,
+ x, y,
+ 0, 0,
+ 0, 0,
+ width, height);
+ surface->base.is_clear = FALSE;
+ surface->owns_data = mem != NULL;
+
+ return surface;
+
+cleanup_image:
+ pixman_image_unref (image);
+cleanup_mem:
+ free (mem);
+cleanup:
+ return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
+}
+
cairo_image_transparency_t
_cairo_image_analyze_transparency (cairo_image_surface_t *image)
{