Updated 'push and pull' patch for Cairo (was Re: [Cairo] compiling on Slackware 9.0)

Eric Christopherson rakko at charter.net
Wed Aug 6 14:35:30 PDT 2003


On Wed, Aug 06, 2003 at 11:39:13AM -0400, Carl Worth wrote:
> On Aug 6, Roman Bednarek wrote:
>  >   Thanks for your help everything is compiling fine now.
> 
> That's good to hear.
> 
>  > But every test program from xrtest crashes as an example xrtest, stack
>  > under gdb:
>  > #0  *INT_IcComposite (op=0 '\0', iSrc=0x0, iMask=0x80510e8, iDst=0x0,
>  >     xSrc=1073784128, ySrc=-1073744024, xMask=0, yMask=0, xDst=134541232,
>  >     yDst=0, width=0, height=134541232) at ic.c:882
> 
> This symptom looks typical of what happens right now when your X
> server doesn't support the Render extension.
> 
> Graydon Hoare contributed a patch that properly enables client-side
> rendering when Render is not available:
> 
> http://cairographics.org/pipermail/cairo/2003-July/000278.html

I've just tried my hand and 'porting' Graydon's patch to apply to the
current CVS. It's attached for anyone who's interested in trying it before
Carl uploads what he has.

-- 
Furrfu!		r a k k o  at  c h a r t e r  dot  n e t
-------------- next part --------------
diff -up src-old/cairo_surface.c src/cairo_surface.c
--- src-old/cairo_surface.c	2003-08-06 16:18:31.000000000 -0500
+++ src/cairo_surface.c	2003-08-06 16:22:49.000000000 -0500
@@ -77,7 +77,6 @@ cairo_surface_create_for_drawable (Displ
 
     surface->dpy = dpy;
     surface->image_data = NULL;
-    surface->icimage = NULL;
 
     surface->type = CAIRO_SURFACE_TYPE_DRAWABLE;
     surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
@@ -99,6 +98,9 @@ cairo_surface_create_for_drawable (Displ
 						 : XRenderFindStandardFormat (dpy, format),
 						 0, NULL);
 
+    surface->icimage = NULL;
+    surface->repeating = 0;
+
     return surface;
 }
 slim_hidden_def(cairo_surface_create_for_drawable)
@@ -213,6 +215,7 @@ cairo_surface_create_for_image (char		*d
     surface->picture = 0;
 
     surface->icimage = image;
+    surface->repeating = 0;
 
     return surface;
 }
@@ -390,12 +393,57 @@ cairo_surface_put_image (cairo_surface_t
     return CAIRO_STATUS_SUCCESS;
 }
 
+static void 
+analyze_mask (int xmask, int *icshift, int *icmask, int *nbits)
+{
+  *icshift = 0;
+  *icmask = 0;
+  *nbits = 0;
+
+  if (xmask == 0)
+      return;
+
+  while ((xmask & 1) == 0)
+    {
+      (*icshift)++;
+      xmask >>= 1;
+    }
+
+  while ((xmask & 1) == 1)
+    {
+      (*icmask) <<= 1;
+      (*icmask) |= 1;
+      (*nbits)++;
+      xmask >>= 1;
+    }
+}
+
+#define PICT_TYPE_OTHER	0
+#define PICT_TYPE_A	1
+#define PICT_TYPE_ARGB	2
+#define PICT_TYPE_ABGR	3
+#define PICT_TYPE_COLOR	4
+#define PICT_TYPE_GRAY	5
+#define PICT_FORMAT(bpp,type,a,r,g,b)	(((bpp) << 24) |  \
+					 ((type) << 16) | \
+					 ((a) << 12) | \
+					 ((r) << 8) | \
+					 ((g) << 4) | \
+					 ((b)))
+
+
 /* XXX: Symmetry demands an cairo_surface_get_image as well. */
 
 void
 _cairo_surface_pull_image (cairo_surface_t *surface)
 {
-/* XXX: NYI (Also needs support for pictures with external alpha.)
+    int x, y;
+    unsigned int width, height, bwidth, depth;
+    Window root;
+
+    if (! surface)
+      return;
+
     if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
 	return;
 
@@ -404,46 +452,99 @@ _cairo_surface_pull_image (cairo_surface
 	surface->icimage = NULL;
     }
 
-    _cairo_surface_ensure_GC (surface);
+    _cairo_surface_ensure_gc (surface);
+    
+    XGetGeometry(surface->dpy, 
+		 surface->drawable, 
+		 &root, &x, &y, &width, &height, &bwidth, &depth);
+
     surface->ximage = XGetImage (surface->dpy,
 				 surface->drawable,
-				 surface->gc,
 				 0, 0,
 				 width, height,
 				 AllPlanes, ZPixmap);
-    
-    surface->icimage = IcImageCreateForData (image->data,
-					     IcFormat *format,
-					     int width, int height,
-					     int bpp, int stride);
-*/
+
+    IcFormat fmt;    
+    fmt.depth = surface->ximage->depth;
+    int alphabits, redbits, greenbits, bluebits, type;
+
+    // HACK: find a proper way to pick up on the drawable's picture format,
+    // or store out of band, or something.
+
+    if (fmt.depth == 8
+	&& surface->ximage->red_mask == 0
+	&& surface->ximage->green_mask == 0
+	&& surface->ximage->blue_mask == 0)
+      {
+	// this is an alpha-only mask pixmap we're pulling a copy of
+	alphabits = 8;
+	redbits = greenbits = bluebits = 0;
+	fmt.redMask = fmt.greenMask = fmt.blueMask = 0;
+	fmt.red = fmt.green = fmt.blue = 0;
+	type = PICT_TYPE_A;
+      }
+
+    else 
+      {	
+	// this is a "normal" pixmap we're pulling a copy of
+	analyze_mask (surface->ximage->red_mask, 
+		      &(fmt.red), &(fmt.redMask), &redbits);
+	
+	analyze_mask (surface->ximage->green_mask, 
+		      &(fmt.green), &(fmt.greenMask), &greenbits);
+	
+	analyze_mask (surface->ximage->blue_mask, &(fmt.blue), 
+		      &(fmt.blueMask), &bluebits);
+
+	alphabits = 0;
+	fmt.alpha = 0;
+	fmt.alphaMask = 0;
+	type = PICT_TYPE_ABGR;
+      }
+
+    fmt.format_name = PICT_FORMAT(surface->ximage->bits_per_pixel,
+				  type, alphabits, redbits, greenbits, bluebits);
+
+    surface->icimage = IcImageCreateForData ((IcBits *)(surface->ximage->data),
+					     &fmt,
+					     surface->ximage->width, 
+					     surface->ximage->height,
+					     surface->ximage->bits_per_pixel, 
+					     surface->ximage->bytes_per_line);
+
+    IcImageSetRepeat (surface->icimage, surface->repeating);
+    IcImageSetTransform (surface->icimage, (IcTransform *) &(surface->xtransform));
+
+    /* XXX: Add support here for pictures with external alpha. */
 }
 
 void
 _cairo_surface_push_image (cairo_surface_t *surface)
 {
-/* XXX: NYI
+    if (! surface)
+      return;
+
     if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
 	return;
 
     if (surface->ximage == NULL)
 	return;
 
-    _cairo_surface_ensure_GC (surface);
+    _cairo_surface_ensure_gc (surface);
     XPutImage (surface->dpy,
 	       surface->drawable,
 	       surface->gc,
 	       surface->ximage,
 	       0, 0,
 	       0, 0,
-	       width, height);
+	       surface->ximage->width, 
+	       surface->ximage->height);
 
-    * Foolish XDestroyImage thinks it can free my data, but I won't
-       stand for it. *
+    /* Foolish XDestroyImage thinks it can free my data, but I won't
+       stand for it. */
     surface->ximage->data = NULL;
     XDestroyImage(surface->ximage);
     surface->ximage = NULL;
-*/
 }
 
 /* XXX: We may want to move to projective matrices at some point. If
@@ -554,6 +655,8 @@ cairo_surface_clip_restore (cairo_surfac
 cairo_status_t
 cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
 {
+    surface->repeating = 1;
+    
     if (surface->picture) {
 	unsigned long mask;
 	XRenderPictureAttributes pa;
diff -up src-old/cairoint.h src/cairoint.h
--- src-old/cairoint.h	2003-08-06 16:18:31.000000000 -0500
+++ src/cairoint.h	2003-08-06 16:23:16.000000000 -0500
@@ -240,6 +240,10 @@ struct cairo_surface {
 
     /* For TYPE_ICIMAGE */
     IcImage *icimage;
+
+    /* For temporary local copy of TYPE_DRAWABLE */
+    int repeating;
+    XImage * ximage;
 };
 
 /* XXX: Right now, the cairo_color structure puts unpremultiplied


More information about the cairo mailing list