[cairo-commit] cairo/src cairo-xlib.h, 1.8, 1.9 cairo.c, 1.56, 1.57 cairo.h, 1.80, 1.81 cairo_xlib_surface.c, 1.47, 1.48

Owen Taylor commit at pdx.freedesktop.org
Tue Mar 15 16:25:33 PST 2005


Committed by: otaylor

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv13550/src

Modified Files:
	cairo-xlib.h cairo.c cairo.h cairo_xlib_surface.c 
Log Message:
2005-03-15  Owen Taylor  <otaylor at redhat.com>

        * src/cairo-xlib.h src/cairo_xlib_surface.c: Rework set
        of contructors for XLib surfaces. Add
        cairo_xlib_surface_set_size().

        * src/cairo-xlib.h src/cairo_xlib_surface.c: Add
        cairo_xlib_surface_set_device_offset().

        * src/cairo_xlib_surface.c (cairo_xlib_surface_set_clip_region):
        Rewrite for clarity and efficiency.

        * src/cairo_xlib_surface.c (_get_image_surface): Use a
        temporary pixmap to avoid possible BadMatch when fetch
        from windows.

        * src/cairo.[ch] src/cairo-xlib.h: Fix some parameter names
        for the docs.

        * doc/public/cairo-sections.txt: Update


Index: cairo-xlib.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cairo-xlib.h	22 Feb 2005 19:35:03 -0000	1.8
+++ cairo-xlib.h	16 Mar 2005 00:25:30 -0000	1.9
@@ -45,29 +45,45 @@
 
 CAIRO_BEGIN_DECLS
 
-/* XXX: This shold be renamed to cairo_set_target_xlib to match the
+/* XXX: This should be renamed to cairo_set_target_xlib to match the
  * other backends */
 void
 cairo_set_target_drawable (cairo_t	*cr,
 			   Display	*dpy,
 			   Drawable	drawable);
 
-/* XXX: This is a mess from the user's POV. Should the Visual or the
-   cairo_format_t control what render format is used? Maybe I can have
-   cairo_surface_create_for_window with a visual, and
-   cairo_surface_create_for_pixmap with a cairo_format_t. Would that work?
-*/
+cairo_surface_t *
+cairo_xlib_surface_create_for_pixmap (Display        *dpy,
+				      Pixmap	      pixmap,
+				      cairo_format_t  format);
+
+cairo_surface_t *
+cairo_xlib_surface_create_for_pixmap_with_visual (Display  *dpy,
+						  Pixmap    pixmap,
+						  Visual   *visual);
+
+cairo_surface_t *
+cairo_xlib_surface_create_for_window_with_visual (Display  *dpy,
+						  Window    window,
+						  Visual   *visual);
+
+/* Deprecated in favor of the more specific functions above */
 cairo_surface_t *
 cairo_xlib_surface_create (Display		*dpy,
 			   Drawable		drawable,
 			   Visual		*visual,
 			   cairo_format_t	format,
 			   Colormap		colormap);
-  
-/* XXX: This has been proposed
-cairo_status_t
-cairo_xlib_surface_set_size (cairo_surface_t *surface, int width, int height);
-*/
+
+void
+cairo_xlib_surface_set_size (cairo_surface_t *surface,
+			     int              width,
+			     int              height);
+
+void
+cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
+				      int              x_offset,
+				      int              y_offset);
 
 CAIRO_END_DECLS
 

Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- cairo.c	11 Mar 2005 22:29:15 -0000	1.56
+++ cairo.c	16 Mar 2005 00:25:30 -0000	1.57
@@ -1525,7 +1525,7 @@
  * @x: return value for X coordinate of the current point
  * @y: return value for Y coordinate of the current point
  * 
- * Returns the current point of the current path, which is
+ * Gets the current point of the current path, which is
  * conceptually the final point reached by the path so far.
  *
  * The current point is returned in the user-space coordinate

Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -d -r1.80 -r1.81
--- cairo.h	11 Mar 2005 22:29:15 -0000	1.80
+++ cairo.h	16 Mar 2005 00:25:30 -0000	1.81
@@ -875,7 +875,7 @@
 cairo_status_t
 cairo_surface_set_user_data (cairo_surface_t		 *surface,
 			     const cairo_user_data_key_t *key,
-			     void			 *data,
+			     void			 *user_data,
 			     cairo_destroy_func_t	 destroy);
 
 /* Image-surface functions */

Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- cairo_xlib_surface.c	4 Mar 2005 02:39:06 -0000	1.47
+++ cairo_xlib_surface.c	16 Mar 2005 00:25:30 -0000	1.48
@@ -37,6 +37,15 @@
 #include "cairoint.h"
 #include "cairo-xlib.h"
 
+typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
+
+typedef enum {
+    CAIRO_XLIB_PIXMAP,
+    CAIRO_XLIB_WINDOW
+} cairo_xlib_drawable_type_t;
+
+static void _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);
+
 /**
  * cairo_set_target_drawable:
  * @cr: a #cairo_t
@@ -78,24 +87,29 @@
     cairo_surface_destroy (surface);
 }
 
-typedef struct _cairo_xlib_surface {
+struct _cairo_xlib_surface {
     cairo_surface_t base;
 
     Display *dpy;
     GC gc;
     Drawable drawable;
-    int owns_pixmap;
+    cairo_bool_t owns_pixmap;
     Visual *visual;
     cairo_format_t format;
 
     int render_major;
     int render_minor;
 
+    cairo_xlib_drawable_type_t type;
     int width;
     int height;
+    int depth;
+
+    int x_offset;
+    int y_offset;
 
     Picture picture;
-} cairo_xlib_surface_t;
+};
 
 #define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor)	\
 	(((surface)->render_major > major) ||			\
@@ -137,16 +151,6 @@
 }
 
 static cairo_surface_t *
-_cairo_xlib_surface_create_with_size (Display		*dpy,
-				      Drawable		drawable,
-				      Visual		*visual,
-				      cairo_format_t	format,
-				      Colormap		colormap,
-				      int               width,
-				      int               height);
-
-
-static cairo_surface_t *
 _cairo_xlib_surface_create_similar (void		*abstract_src,
 				    cairo_format_t	format,
 				    int			drawable,
@@ -173,13 +177,10 @@
 			 _CAIRO_FORMAT_DEPTH (format));
     
     surface = (cairo_xlib_surface_t *)
-	_cairo_xlib_surface_create_with_size (dpy, pix, NULL, format,
-					      DefaultColormap (dpy, scr),
-					      width, height);
-    surface->owns_pixmap = 1;
-
-    surface->width = width;
-    surface->height = height;
+	cairo_xlib_surface_create_for_pixmap (dpy, pix, format);
+    cairo_xlib_surface_set_size (&surface->base, width, height);
+				 
+    surface->owns_pixmap = TRUE;
 
     return &surface->base;
 }
@@ -197,7 +198,7 @@
     if (surface->gc)
 	XFreeGC (surface->dpy, surface->gc);
 
-    surface->dpy = 0;
+    surface->dpy = NULL;
 
     free (surface);
 }
@@ -217,30 +218,53 @@
 {
     cairo_image_surface_t *image;
     XImage *ximage;
-    Window root_ignore;
-    int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
     int x1, y1, x2, y2;
 
-    XGetGeometry (surface->dpy, 
-		  surface->drawable, 
-		  &root_ignore, &x_ignore, &y_ignore,
-		  &surface->width, &surface->height,
-		  &bwidth_ignore, &depth_ignore);
-
     x1 = 0;
     y1 = 0;
-    x2 = surface->width;
-    y2 = surface->height;
+    
+    if (surface->width >= 0 && surface->height >= 0) {
+	x2 = surface->width;
+	y2 = surface->height;
+    } else {
+	int width, height;
+	Window root_ignore;
+	int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
+	
+	XGetGeometry (surface->dpy, 
+		      surface->drawable, 
+		      &root_ignore, &x_ignore, &y_ignore,
+		      &width, &height,
+		      &bwidth_ignore, &depth_ignore);
+
+	/* The size of a pixmap can't change, so we store
+	 * the information to avoid having to get it again
+	 */
+	if (surface->type == CAIRO_XLIB_PIXMAP) {
+	    surface->width = width;
+	    surface->height = height;
+	}
+	
+	x2 = width;
+	y2 = height;
+    }
 
     if (interest_rect) {
-	if (interest_rect->x > x1)
-	    x1 = interest_rect->x;
-	if (interest_rect->y > y1)
-	    y1 = interest_rect->y;
-	if (interest_rect->x + interest_rect->width < x2)
-	    x2 = interest_rect->x + interest_rect->width;
-	if (interest_rect->y + interest_rect->height < y2)
-	    y2 = interest_rect->y + interest_rect->height;
+	cairo_rectangle_t rect;
+	
+	rect.x = interest_rect->x + surface->x_offset;
+	rect.y = interest_rect->y + surface->x_offset;
+	rect.width = interest_rect->width;
+	rect.height = interest_rect->width;
+    
+	if (rect.x > x1)
+	    x1 = rect.x;
+	if (rect.y > y1)
+	    y1 = rect.y;
+	if (rect.x + rect.width < x2)
+	    x2 = rect.x + rect.width;
+	if (rect.y + rect.height < y2)
+	    y2 = rect.y + rect.height;
 
 	if (x1 >= x2 || y1 >= y2) {
 	    *image_out = NULL;
@@ -249,18 +273,46 @@
     }
 
     if (image_rect) {
-	image_rect->x = x1;
-	image_rect->y = y1;
+	image_rect->x = x1 - surface->x_offset;
+	image_rect->y = y1 - surface->y_offset;
 	image_rect->width = x2 - x1;
 	image_rect->height = y2 - y1;
     }
 
-    /* XXX: This should try to use the XShm extension if availible */
-    ximage = XGetImage (surface->dpy,
-			surface->drawable,
-			x1, y1,
-			x2 - x1, y2 - y1,
-			AllPlanes, ZPixmap);
+    /* XXX: This should try to use the XShm extension if available */
+    
+    if (surface->type == CAIRO_XLIB_WINDOW) {
+
+	/* XGetImage from a window is dangerous because it can
+	 * produce errors if the window is unmapped or partially
+	 * outside the screen. We could check for errors and
+	 * retry, but to keep things simple, we just create a
+	 * temporary pixmap
+	 */
+	Pixmap pixmap = XCreatePixmap (surface->dpy,
+				       surface->drawable,
+				       x2 - x1, y2 - y1,
+				       surface->depth);
+	_cairo_xlib_surface_ensure_gc (surface);
+
+	XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
+		   x1, y1, x2 - x1, y2 - y1, 0, 0);
+	
+	ximage = XGetImage (surface->dpy,
+			    pixmap,
+			    0, 0,
+			    x2 - x1, y2 - y1,
+			    AllPlanes, ZPixmap);
+	
+	XFreePixmap (surface->dpy, pixmap);
+					
+    } else {
+	ximage = XGetImage (surface->dpy,
+			    surface->drawable,
+			    x1, y1,
+			    x2 - x1, y2 - y1,
+			    AllPlanes, ZPixmap);
+    }
 
     if (surface->visual) {
 	cairo_format_masks_t masks;
@@ -303,10 +355,14 @@
 static void
 _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
 {
+    XGCValues gcv;
+
     if (surface->gc)
 	return;
 
-    surface->gc = XCreateGC (surface->dpy, surface->drawable, 0, NULL);
+    gcv.graphics_exposures = False;
+    surface->gc = XCreateGC (surface->dpy, surface->drawable,
+			     GCGraphicsExposures, &gcv);
 }
 
 static cairo_status_t
@@ -340,7 +396,7 @@
 
     _cairo_xlib_surface_ensure_gc (surface);
     XPutImage(surface->dpy, surface->drawable, surface->gc,
-	      ximage, 0, 0, dst_x, dst_y,
+	      ximage, 0, 0, dst_x + surface->x_offset, dst_y + surface->y_offset,
 	      image->width, image->height);
 
     /* Foolish XDestroyImage thinks it can free my data, but I won't
@@ -679,7 +735,7 @@
 			      src_x + src_attr.x_offset,
 			      src_y + src_attr.y_offset,
 			      0, 0,
-			      dst_x, dst_y,
+			      dst_x + dst->x_offset, dst_y + dst->y_offset,
 			      width, height);
 	}
     }
@@ -692,6 +748,20 @@
     return status;
 }
 
+static void
+_translate_rects (cairo_rectangle_t *rects,
+		  int                num_rects,
+		  int                x_offset,
+		  int                y_offset)
+{
+    int i;
+
+    for (i = 0; i < num_rects; i++) {
+	rects[i].x += x_offset;
+	rects[i].y += y_offset;
+    }
+}
+
 static cairo_int_status_t
 _cairo_xlib_surface_fill_rectangles (void			*abstract_surface,
 				     cairo_operator_t		operator,
@@ -710,6 +780,10 @@
     render_color.blue  = color->blue_short;
     render_color.alpha = color->alpha_short;
 
+    if (surface->x_offset != 0 || surface->y_offset != 0)
+	_translate_rects (rects, num_rects,
+			  surface->x_offset, surface->y_offset);
+
     /* XXX: This XRectangle cast is evil... it needs to go away somehow. */
     XRenderFillRectangles (surface->dpy,
 			   _render_operator (operator),
@@ -719,6 +793,31 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+static void
+_translate_traps (cairo_trapezoid_t *traps,
+		  int                num_traps,
+		  int                x_offset,
+		  int                y_offset)
+{
+    cairo_fixed_t xoff, yoff;
+    int i;
+
+    xoff = _cairo_fixed_from_int (x_offset);
+    yoff = _cairo_fixed_from_int (y_offset);
+
+    for (i = 0; i < num_traps; i++) {
+	traps[i].top += yoff;
+	traps[i].bottom += yoff;
+	traps[i].left.p1.x += xoff;
+	traps[i].left.p1.y += yoff;
+	traps[i].left.p2.x += xoff;
+	traps[i].left.p2.y += yoff;
+	traps[i].right.p1.x += xoff;
+	traps[i].right.p1.y += yoff;
+	traps[i].right.p2.x += xoff;
+	traps[i].right.p2.y += yoff;
+    }
+}
 static cairo_int_status_t
 _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	operator,
 					  cairo_pattern_t	*pattern,
@@ -749,6 +848,9 @@
     if (status)
 	return status;
     
+    if (dst->x_offset != 0 || dst->y_offset != 0)
+	_translate_traps (traps, num_traps, dst->x_offset, dst->y_offset);
+
     if (traps[0].left.p1.y < traps[0].left.p2.y) {
 	render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
 	render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y);
@@ -757,8 +859,8 @@
 	render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
     }
 
-    render_src_x = src_x + render_reference_x - dst_x;
-    render_src_y = src_y + render_reference_y - dst_y;
+    render_src_x = src_x + render_reference_x - (dst_x + dst->x_offset);
+    render_src_y = src_y + render_reference_y - (dst_y + dst->y_offset);
 
     /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
     status = _cairo_xlib_surface_set_attributes (src, &attributes);
@@ -789,66 +891,55 @@
 }
 
 static cairo_int_status_t
-_cairo_xlib_surface_set_clip_region (void *abstract_surface,
+_cairo_xlib_surface_set_clip_region (void              *abstract_surface,
 				     pixman_region16_t *region)
 {
-
-    Region xregion;
-    XRectangle xr;
-    XRectangle *rects = NULL;
-    XGCValues gc_values;
-    pixman_box16_t *box;
-    cairo_xlib_surface_t *surf;
-    int n, m;
-
-    surf = (cairo_xlib_surface_t *) abstract_surface;
+    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
     if (region == NULL) {
-	/* NULL region == reset the clip */
-	xregion = XCreateRegion();
-	xr.x = 0;
-	xr.y = 0;
-	xr.width = surf->width;
-	xr.height = surf->height;
-	XUnionRectWithRegion (&xr, xregion, xregion);
-	rects = malloc(sizeof(XRectangle));
-	if (rects == NULL)
-	    return CAIRO_STATUS_NO_MEMORY;
-	rects[0] = xr;
-	m = 1;
-
+	if (surface->gc)
+	    XSetClipMask (surface->dpy, surface->gc, None);
+	
+	if (surface->picture) {
+	    XRenderPictureAttributes pa;
+	    pa.clip_mask = None;
+	    XRenderChangePicture (surface->dpy, surface->picture,
+				  CPClipMask, &pa);
+	}
     } else {
-	n = pixman_region_num_rects (region);
-	/* XXX: Are we sure these are the semantics we want for an
-	 * empty, (not null) region? */
-	if (n == 0)
-	    return CAIRO_STATUS_SUCCESS;
-	rects = malloc(sizeof(XRectangle) * n);
-	if (rects == NULL)
-	    return CAIRO_STATUS_NO_MEMORY;
-	box = pixman_region_rects (region);
-	xregion = XCreateRegion();
+	pixman_box16_t *boxes;
+	XRectangle *rects = NULL;
+	int n_boxes, i;
 	
-	m = n;
-	for (; n > 0; --n, ++box) {
-	    xr.x = (short) box->x1;
-	    xr.y = (short) box->y1;
-	    xr.width = (unsigned short) (box->x2 - box->x1);
-	    xr.height = (unsigned short) (box->y2 - box->y1);
-	    rects[n-1] = xr;
-	    XUnionRectWithRegion (&xr, xregion, xregion);
-	}    
+	n_boxes = pixman_region_num_rects (region);
+	if (n_boxes > 0) {
+	    rects = malloc (sizeof(XRectangle) * n_boxes);
+	    if (rects == NULL)
+		return CAIRO_STATUS_NO_MEMORY;
+	} else {
+	    rects = NULL;
+	}
+
+	boxes = pixman_region_rects (region);
+	
+	for (i = 0; i < n_boxes; i++) {
+	    rects[i].x = boxes[i].x1 + surface->x_offset;
+	    rects[i].y = boxes[i].y1 + surface->y_offset;
+	    rects[i].width = boxes[i].x2 - boxes[i].x1;
+	    rects[i].height = boxes[i].y2 - boxes[i].y1;
+	}
+
+	if (surface->gc)
+	    XSetClipRectangles(surface->dpy, surface->gc,
+			       0, 0, rects, n_boxes, YXSorted);
+	if (surface->picture)
+	    XRenderSetPictureClipRectangles (surface->dpy, surface->picture,
+					     0, 0, rects, n_boxes);
+
+	if (rects)
+	    free (rects);
     }
     
-    _cairo_xlib_surface_ensure_gc (surf); 
-    XGetGCValues(surf->dpy, surf->gc, GCGraphicsExposures, &gc_values);
-    XSetGraphicsExposures(surf->dpy, surf->gc, False);
-    XSetClipRectangles(surf->dpy, surf->gc, 0, 0, rects, m, Unsorted);
-    free(rects);
-    if (surf->picture)
-	XRenderSetPictureClipRegion (surf->dpy, surf->picture, xregion);
-    XDestroyRegion(xregion);
-    XSetGraphicsExposures(surf->dpy, surf->gc, gc_values.graphics_exposures);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -885,16 +976,13 @@
 };
 
 static cairo_surface_t *
-_cairo_xlib_surface_create_with_size (Display		*dpy,
-				      Drawable		drawable,
-				      Visual		*visual,
-				      cairo_format_t	format,
-				      Colormap		colormap,
-				      int               width,
-				      int               height)
+_cairo_xlib_surface_create_internal (Display		       *dpy,
+				     Drawable		        drawable,
+				     cairo_xlib_drawable_type_t type,
+				     Visual		       *visual,
+				     cairo_format_t	        format)
 {
     cairo_xlib_surface_t *surface;
-    int render_standard;
 
     surface = malloc (sizeof (cairo_xlib_surface_t));
     if (surface == NULL)
@@ -902,48 +990,85 @@
 
     _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
 
-    surface->visual = visual;
-    surface->format = format;
+    surface->type = type;
 
     surface->dpy = dpy;
 
-    surface->gc = 0;
+    surface->gc = NULL;
     surface->drawable = drawable;
-    surface->owns_pixmap = 0;
-    surface->visual = visual;
-    surface->width = width;
-    surface->height = height;
+    surface->owns_pixmap = FALSE;
+    surface->width = -1;
+    surface->height = -1;
+    surface->x_offset = 0;
+    surface->y_offset = 0;
     
+    if (visual) {
+	int i, j, k;
+
+	surface->format = (cairo_format_t)-1;
+
+	/* This is ugly, but we have to walk over all visuals
+	 * for the display to find the depth.
+	 */
+	for (i = 0; i < ScreenCount (dpy); i++) {
+	    Screen *screen = ScreenOfDisplay (dpy, i);
+	    for (j = 0; j < screen->ndepths; j++) {
+		Depth *depth = &screen->depths[j];
+		for (k = 0; k < depth->nvisuals; k++) {
+		    if (&depth->visuals[k] == visual)
+			surface->depth = depth->depth;
+		    goto found;
+		}
+	    }
+	}
+    found:
+	
+	surface->visual = visual;
+	
+    } else {
+	surface->format = format;
+	surface->depth = _CAIRO_FORMAT_DEPTH (format);
+	surface->visual = NULL;
+    }
+
     if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
 	surface->render_major = -1;
 	surface->render_minor = -1;
     }
 
-    switch (format) {
-    case CAIRO_FORMAT_A1:
-	render_standard = PictStandardA1;
-	break;
-    case CAIRO_FORMAT_A8:
-	render_standard = PictStandardA8;
-	break;
-    case CAIRO_FORMAT_RGB24:
-	render_standard = PictStandardRGB24;
-	break;
-    case CAIRO_FORMAT_ARGB32:
-    default:
-	render_standard = PictStandardARGB32;
-	break;
-    }
+    if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
+	XRenderPictFormat *render_format;
+
+	if (visual) {
+	    render_format = XRenderFindVisualFormat (dpy, visual);
+	    
+	} else {
+
+	    int render_standard;
+	
+	    switch (format) {
+	    case CAIRO_FORMAT_A1:
+		render_standard = PictStandardA1;
+		break;
+	    case CAIRO_FORMAT_A8:
+		render_standard = PictStandardA8;
+		break;
+	    case CAIRO_FORMAT_RGB24:
+		render_standard = PictStandardRGB24;
+		break;
+	    case CAIRO_FORMAT_ARGB32:
+	    default:
+		render_standard = PictStandardARGB32;
+		break;
+	    }
+
+	    render_format = XRenderFindStandardFormat (dpy, render_standard);
+	}
 
-    /* XXX: I'm currently ignoring the colormap. Is that bad? */
-    if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface))
 	surface->picture = XRenderCreatePicture (dpy, drawable,
-						 visual ?
-						 XRenderFindVisualFormat (dpy, visual) :
-						 XRenderFindStandardFormat (dpy, render_standard),
-						 0, NULL);
-    else
-	surface->picture = 0;
+						 render_format, 0, NULL);
+    } else
+	surface->picture = None;
 
     return (cairo_surface_t *) surface;
 }
@@ -955,24 +1080,158 @@
 			   cairo_format_t	format,
 			   Colormap		colormap)
 {
-    Window window_ignore;
-    unsigned int int_ignore;
-    unsigned int width, height;
-
-    /* XXX: This call is a round-trip. We probably want to instead (or
-     * also?) export a version that accepts width/height. Then, we'll
-     * likely also need a resize function too.
+    /* Just assume a window ... slow but safe. This function is
+     * going away anyways
      */
-    XGetGeometry(dpy, drawable,
-		 &window_ignore, &int_ignore, &int_ignore,
-		 &width, &height,
-		 &int_ignore, &int_ignore);
-
-    return _cairo_xlib_surface_create_with_size (dpy, drawable, visual, format,
-						 colormap, width, height);
+    return _cairo_xlib_surface_create_internal (dpy, drawable,
+						CAIRO_XLIB_WINDOW,
+						visual,
+						format);
 }
 DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);
 
+/**
+ * cairo_xlib_surface_create_for_pixmap:
+ * @dpy: an X display
+ * @pixmap: an X pixmap
+ * @format: a standard Cairo pixel data format. The depth (number of
+ *          of bits used) for the format must match the depth of
+ *          @pixmap.
+ *
+ * Creates an Xlib surface that draws to the given pixmap.
+ * The way that colors are represented in the pixmap is specified
+ * by giving one of Cairo's standard pixel data formats.
+ *
+ * For maximum efficiency, if you know the size of the pixmap,
+ * you should call cairo_xlib_surface_set_size().
+ * 
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_xlib_surface_create_for_pixmap (Display        *dpy,
+				      Pixmap	      pixmap,
+				      cairo_format_t  format)
+{
+    return _cairo_xlib_surface_create_internal (dpy, pixmap,
+						CAIRO_XLIB_PIXMAP,
+						NULL, format);
+}
+
+/**
+ * cairo_xlib_surface_create_for_pixmap_with_visual:
+ * @dpy: an X display
+ * @pixmap: an  X pixmap
+ * @visual: the visual to use for drawing to @pixmap. The depth
+ *          of the visual must match the depth of the pixmap.
+ *          Currently, only TrueColor visuals are fully supported.
+ * 
+ * Creates an Xlib surface that draws to the given pixmap.
+ * The way that colors are represented in the pixmap is specified
+ * by an X visual.
+ * 
+ * Normally, you would use this function instead of
+ * cairo_xlib_surface_create_for_pixmap() when you double-buffering by
+ * using Cairo to draw to pixmap and then XCopyArea() to copy the
+ * results to a window. In that case, @visual is the visual of the
+ * window.
+ *
+ * For maximum efficiency, if you know the size of the pixmap,
+ * you should call cairo_xlib_surface_set_size().
+ * 
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_xlib_surface_create_for_pixmap_with_visual (Display  *dpy,
+						  Pixmap    pixmap,
+						  Visual   *visual)
+{
+    return _cairo_xlib_surface_create_internal (dpy, pixmap,
+						CAIRO_XLIB_PIXMAP,
+						visual,
+						(cairo_format_t)-1);
+}
+
+/**
+ * cairo_xlib_surface_create_for_window_with_visual:
+ * @dpy: an X display
+ * @window: an X window 
+ * @visual: the visual of @window. Currently, only TrueColor visuals
+ *          are fully supported.
+ * 
+ * Creates a new XLib backend surface that draws to the given Window.
+ *
+ * For maximum efficiency, you should use cairo_xlib_surface_set_size()
+ * to inform Cairo of the size of the window.
+ * 
+ * Return value: the newly created surface. 
+ **/
+cairo_surface_t *
+cairo_xlib_surface_create_for_window_with_visual (Display  *dpy,
+						  Window    window,
+						  Visual   *visual)
+{
+    return _cairo_xlib_surface_create_internal (dpy, window,
+						CAIRO_XLIB_WINDOW,
+						visual,
+						(cairo_format_t)-1);
+}
+
+/**
+ * cairo_xlib_surface_set_size:
+ * @surface: a #cairo_surface_t for the XLib backend
+ * @width: the new width of the surface
+ * @height: the new height of the surface
+ * 
+ * Informs Cairo of the size of the X drawable underlying the
+ * surface. This allows Cairo to avoid querying the server for the
+ * size, which can be a significant performance bottleneck.
+ *
+ * For a surface created for a pixmap, it is only necessary to call
+ * this function once, since pixmaps have a fixed size. For a surface
+ * created for a window, you should call this function each time the
+ * window changes size. (For a subwindow, you are normally resizing
+ * the window yourself, but for a toplevel window, it is necessary
+ * to listen for ConfigureNotify events.)
+ **/
+void
+cairo_xlib_surface_set_size (cairo_surface_t *surface,
+			     int              width,
+			     int              height)
+{
+    cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
+
+    xlib_surface->width = width;
+    xlib_surface->height = height;
+}
+
+/**
+ * cairo_xlib_surface_set_device_offset:
+ * @surface: a #cairo_surface_t for the XLib backend
+ * @x_offset: offset in the X direction, in pixels
+ * @y_offset: offset in the Y direction, in pixels
+ * 
+ * Sets an offset that is added to the device coordinates determined
+ * by the CTM when drawing to @surface. This is useful when we want
+ * to redirect drawing to a window to a backing pixmap for a portion
+ * of the window in a way that is completely invisible to the user
+ * of the Cairo API. Setting a transformation via cairo_translate() isn't
+ * sufficient to do this, since functions like
+ * cairo_inverse_transform_point() will expose the hidden offset.
+ *
+ * Note that the offset only affects drawing to the surface, not using
+ * the surface in a surface pattern.
+ **/
+void
+cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
+				      int              x_offset,
+				      int              y_offset)
+{
+  cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
+
+  xlib_surface->x_offset = x_offset;
+  xlib_surface->y_offset = y_offset;
+}
+
 /* RENDER glyphset cache code */
 
 typedef struct glyphset_cache {
@@ -1229,8 +1488,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
+	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -1306,8 +1565,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
+	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -1382,8 +1641,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
+	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;




More information about the cairo-commit mailing list