diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-01 16:31:49 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-01 16:36:03 +0000 |
commit | c391093f40472c2300f38d0e5857858f85586b60 (patch) | |
tree | e64ce1e4f706860de65439821ed3659eb3b174c0 | |
parent | 15830fdb1087f18dcd6351de1034a5025b8ed343 (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.h | 7 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 55 |
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) { |