[cairo-commit] src/cairo-xcb-surface.c

Ian Osgood iano at kemper.freedesktop.org
Thu Oct 19 13:49:18 PDT 2006


 src/cairo-xcb-surface.c |   80 ++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 64 insertions(+), 16 deletions(-)

New commits:
diff-tree 8d2f0367527cb23f5902db0526b69b7d83b97f9c (from 8d7a02ed58e06584eb09575e6ca11d0a81094ab6)
Author: Ian Osgood <iano at quirkster.com>
Date:   Thu Oct 19 13:42:04 2006 -0700

    XCB: implement subimage_copy fix
    
    Needs further testing and review.

diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index d104adf..9e2d8d8 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -546,20 +546,71 @@ _cairo_xcb_surface_ensure_gc (cairo_xcb_
 static cairo_status_t
 _draw_image_surface (cairo_xcb_surface_t    *surface,
 		     cairo_image_surface_t  *image,
+		     int                    src_x,
+		     int                    src_y,
+		     int                    width,
+		     int                    height,
 		     int                    dst_x,
 		     int                    dst_y)
 {
-    int bpp, data_len;
+    int bpp, bpl;
+    uint32_t data_len;
+    uint8_t *data, left_pad=0;
+
+    /* equivalent of XPutImage(..., src_x,src_y, dst_x,dst_y, width,height); */
+    /* XXX: assumes image and surface formats and depths are the same */
+    /* XXX: assumes depth is a multiple of 8 (not bitmap) */
+
+    /* fit src_{x,y,width,height} within image->{0,0,width,height} */
+    if (src_x < 0) {
+	width += src_x;
+	src_x = 0;
+    }
+    if (src_y < 0) {
+	height += src_y;
+	src_y = 0;
+    }
+    if (width + src_x > image->width)
+	width = image->width - src_x;
+    if (height + src_y > image->height)
+	height = image->height - src_y;
+    if (width <= 0 || height <= 0)
+	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_xcb_surface_ensure_gc (surface);
     bpp = _bits_per_pixel(surface->dpy, image->depth);
-    data_len = _bytes_per_line(surface->dpy, image->width, bpp) * image->height;
-    xcb_put_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP, surface->drawable, surface->gc,
-	      image->width,
-	      image->height,
-	      dst_x, dst_y,
-	      /* left_pad */ 0, image->depth,
-	      data_len, image->data);
+    /* XXX: could use bpl = image->stride? */
+    bpl = _bytes_per_line(surface->dpy, image->width, bpp);
+
+    if (src_x == 0 && width == image->width) {
+	/* can work in-place */
+	data_len = height * bpl;
+	data = image->data + src_y * bpl;
+    } else {
+	/* must copy {src_x,src_y,width,height} into new data */
+	int line = 0;
+	uint8_t *data_line, *image_line;
+	int data_bpl = _bytes_per_line(surface->dpy, width, bpp);
+	data_len = height * data_bpl;
+	data_line = data = malloc(data_len);
+	if (data == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+	image_line = image->data + src_y * bpl + (src_x * bpp / 8);
+	while (line++ < height) {
+	    memcpy(data_line, image_line, data_bpl);
+	    data_line += data_bpl;
+	    image_line += bpl;
+	}
+    }
+    _cairo_xcb_surface_ensure_gc (surface);
+    xcb_put_image (surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
+	surface->drawable, surface->gc,
+	width, height,
+	dst_x, dst_y,
+	left_pad, image->depth,
+	data_len, data);
+
+    if (data < image->data || data >= image->data + image->height * bpl)
+	free(data);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -622,7 +673,8 @@ _cairo_xcb_surface_release_dest_image (v
     cairo_xcb_surface_t *surface = abstract_surface;
 
     /* ignore errors */
-    _draw_image_surface (surface, image, image_rect->x, image_rect->y);
+    _draw_image_surface (surface, image, 0, 0, image->width, image->height,
+			 image_rect->x, image_rect->y);
 
     cairo_surface_destroy (&image->base);
 }
@@ -672,12 +724,8 @@ _cairo_xcb_surface_clone_similar (void		
 	if (clone->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;
 
-	/* can't apply extents; no manpages for XCBPutImage and xcb
-	source from freedesktop currently won't build.  XCBPutImage is not
-	referenced in the XCB source from xcb.freedesktop.org/dist
-	anywhere. */
-
-	_draw_image_surface (clone, image_src, 0, 0);
+	_draw_image_surface (clone, image_src, src_x, src_y,
+			     width, height, src_x, src_y);
 
 	*clone_out = &clone->base;
 


More information about the cairo-commit mailing list