On Monday 27 March 2006 7:39 am, Eric Faurot wrote:
> Hi all,
> 
> Here is a "diff -N -u" updating cairo to 1.0.4.

The diff didn't apply cleanly. I've attached a working
one in case anyone else would like to try.

> More importantly, I have written a (rather simple) workaround to
> support PseudoColor and StaticColor modes on X11. It is not too fast,
> especially on a remote display, but at least it does not crash (I
> hope). It should even produce reasonnable output, provided that
> colormaps are not changed too much after the first calls to cairo
> drawing functions. It might even work on StaticGray/GrayScale
> displays.
> 
> I have tested it on macppc with both wscons and ati drivers, with
> local server, through "ssh -X" and "ssh -Y".  Sample code for testing
> can be found at:
> 
> http://webcvs.cairographics.org/cairo-demo/X11/
> 
> Please test and report, especially those who are stuck with 8 bit
> displays.  I do not plan to write something more complicated/efficient
> for now. So, if someone is interested in improving that fix, please do
> so.

Thanks for writing a fix for the lack of PseudoColor and
StaticColor support in cairo. I tried it and it does fix
the segfault and seems to work well enough. I think your
update should go in. Anyone see a reason why it shouldn't?

-Kurt
Index: Makefile
===================================================================
RCS file: /cvs/ports/graphics/cairo/Makefile,v
retrieving revision 1.5
diff -u -r1.5 Makefile
--- Makefile	10 Jan 2006 08:59:16 -0000	1.5
+++ Makefile	28 Apr 2006 17:02:04 -0000
@@ -2,9 +2,9 @@
 
 COMMENT=		"vector graphics library"
 
-PKGNAME=		${DISTNAME}p0
-DISTNAME=		cairo-1.0.2
-SHARED_LIBS=		cairo	4.3
+PKGNAME=		${DISTNAME}
+DISTNAME=		cairo-1.0.4
+SHARED_LIBS=		cairo	4.4
 CATEGORIES=		graphics
 
 HOMEPAGE=		http://cairographics.org/introduction
Index: distinfo
===================================================================
RCS file: /cvs/ports/graphics/cairo/distinfo,v
retrieving revision 1.2
diff -u -r1.2 distinfo
--- distinfo	4 Nov 2005 01:12:58 -0000	1.2
+++ distinfo	28 Apr 2006 17:02:04 -0000
@@ -1,4 +1,4 @@
-MD5 (cairo-1.0.2.tar.gz) = d0b7111a14f90ec3afa777ec40c44984
-RMD160 (cairo-1.0.2.tar.gz) = 59f309974fdac86253ed9a4d00e564a2fac310eb
-SHA1 (cairo-1.0.2.tar.gz) = 3a425049499b0b067ed4dc60d94b4d0819c0841b
-SIZE (cairo-1.0.2.tar.gz) = 1458903
+MD5 (cairo-1.0.4.tar.gz) = 9002b0e69b3f94831a22d3f2a7735ce2
+RMD160 (cairo-1.0.4.tar.gz) = 40403971bcb6ed9cd4379e8e13a52f515db886cb
+SHA1 (cairo-1.0.4.tar.gz) = 89e72202e5b51a8914fce60f52f7c51ecdea982a
+SIZE (cairo-1.0.4.tar.gz) = 1475777
Index: patches/patch-cairo_pc_in
===================================================================
RCS file: /cvs/ports/graphics/cairo/patches/patch-cairo_pc_in,v
retrieving revision 1.1
diff -u -r1.1 patch-cairo_pc_in
--- patches/patch-cairo_pc_in	10 Jan 2006 08:59:17 -0000	1.1
+++ patches/patch-cairo_pc_in	28 Apr 2006 17:02:04 -0000
@@ -1,7 +1,7 @@
-$OpenBSD: patch-cairo_pc_in,v 1.1 2006/01/10 08:59:17 matthieu Exp $
---- cairo.pc.orig	Thu Aug 18 00:57:45 2005
-+++ cairo.pc.in	Mon Jan  2 22:51:03 2006
-@@ -8,5 +8,5 @@
+$OpenBSD$
+--- cairo.pc.in.orig	Tue Mar 14 03:08:44 2006
++++ cairo.pc.in	Thu Mar 23 14:27:36 2006
+@@ -8,5 +8,5 @@ Description: Multi-platform 2D graphics 
  Version: @VERSION@
  
  @PKGCONFIG_REQUIRES@: @FREETYPE_REQUIRES@ @XRENDER_REQUIRES@ @PNG_REQUIRES@ @GLITZ_REQUIRES@
Index: patches/patch-configure
===================================================================
RCS file: /cvs/ports/graphics/cairo/patches/patch-configure,v
retrieving revision 1.2
diff -u -r1.2 patch-configure
--- patches/patch-configure	4 Nov 2005 01:12:58 -0000	1.2
+++ patches/patch-configure	28 Apr 2006 17:02:04 -0000
@@ -1,7 +1,7 @@
 $OpenBSD: patch-configure,v 1.2 2005/11/04 01:12:58 naddy Exp $
---- configure.orig	Tue Oct  4 02:48:32 2005
-+++ configure	Fri Nov  4 01:35:40 2005
-@@ -24143,7 +24143,8 @@ fi;
+--- configure.orig	Wed Mar 15 20:04:32 2006
++++ configure	Thu Mar 23 14:27:36 2006
+@@ -23996,7 +23996,8 @@ fi;
  if test "x$use_png" = "xyes"; then
    use_png=no
    # libpng13 is GnuWin32's libpng-1.2.8 :-(
Index: patches/patch-src_cairo-xlib-surface_c
===================================================================
RCS file: patches/patch-src_cairo-xlib-surface_c
diff -N patches/patch-src_cairo-xlib-surface_c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_cairo-xlib-surface_c	28 Apr 2006 17:02:04 -0000
@@ -0,0 +1,383 @@
+$OpenBSD$
+--- src/cairo-xlib-surface.c.orig	Wed Mar 15 16:26:51 2006
++++ src/cairo-xlib-surface.c	Sun Mar 26 21:00:36 2006
+@@ -72,6 +72,8 @@ _native_byte_order_lsb (void);
+ 
+ #define CAIRO_ASSUME_PIXMAP	20
+ 
++struct clut_r3g3b2;
++
+ struct _cairo_xlib_surface {
+     cairo_surface_t base;
+ 
+@@ -117,6 +119,9 @@ struct _cairo_xlib_surface {
+     int num_clip_rects;
+ 
+     XRenderPictFormat *format;
++
++    struct clut_r3g3b2 *clut;
++
+ };
+ 
+ #define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor)	\
+@@ -416,6 +421,160 @@ _swap_ximage_to_native (XImage *ximage)
+     }
+ }
+ 
++#if 0
++static void _set_optimal_cmap(Display *dpy, Colormap cmap) {
++    int i, r, g, b;
++    XColor cm[256];
++
++    for (i = 0; i < 256; i++) {
++	r = i >> 5;
++	g = (i >> 2) & 0x7;
++	b = (i << 1) & 0x7;
++	cm[i].pixel = i;
++	cm[i].flags = DoRed | DoGreen | DoBlue;
++	cm[i].red   = r << 13 | r << 10 | r << 7 | r << 4 | r << 1 | r >> 2;
++	cm[i].green = g << 13 | g << 10 | g << 7 | g << 4 | g << 1 | g >> 2;
++	cm[i].blue  = b << 13 | b << 10 | b << 7 | b << 4 | b << 1 | b >> 2;
++    }
++    XStoreColors(dpy, cmap, cm, 256);
++}
++#endif
++
++struct clut_r3g3b2 {
++    struct clut_r3g3b2 *next;
++    Display            *dpy;
++    Colormap           cmap;
++    unsigned char      clut[256 * 3];
++    unsigned char      ilut[256];
++};
++
++static struct clut_r3g3b2 * _get_clut_r3g3b2(Display *dpy, Colormap cmap) {
++    static struct clut_r3g3b2 *first = NULL;
++    int i,j, min, d;
++    struct clut_r3g3b2 *clut;
++    unsigned char *c, r,g,b, r2,g2,b2;
++
++    clut = first;
++    while(clut) {
++	if ( clut->dpy == dpy && clut->cmap == cmap )
++	    return clut;
++	clut = clut->next;
++    }
++    
++    clut = calloc(1, sizeof(*clut));
++    if(clut == NULL)
++	return NULL;
++    
++    clut->next = first;
++    clut->dpy = dpy;
++    clut->cmap = cmap;
++    first = clut;
++
++    /* Construct the clut from Colormap */
++    c = clut->clut;
++    for (i = 0; i < 256; i++) {
++	XColor xcol;
++	xcol.pixel = i;
++	XQueryColor(dpy, cmap, &xcol);
++	c[0] = xcol.red   / 256;
++	c[1] = xcol.green / 256;
++	c[2] = xcol.blue  / 256;
++	c += 3;
++    }
++    /*
++      
++    Find the best matching color in the colormap for all r3g3b2
++    values. The distance is maybe not perceptively valid, but it
++    should not be too bad.
++    
++    */
++    for (i = 0; i < 256; i++) {
++	r = i >> 5;
++	g = (i >> 2) & 0x7;
++	b = (i << 1) & 0x7;
++	min = 255;
++	for(j = 0; j < 256; j++) {
++	    c = clut->clut + j*3;
++	    r2 = c[0] >> 5;
++	    g2 = c[1] >> 5;
++	    b2 = c[2] >> 5;
++	    if ( r2 == r && g2 == g && (b2 & 0x6) == b ) {
++		clut->ilut[i] = j;
++		break;
++	    }
++
++	    /*
++	      
++	    Square make higher bits much more important than lower
++	    ones.
++	    
++	    */
++	    d  = (r2 ^ r) * (r2 ^ r);
++	    d += (g2 ^ g) * (g2 ^ g);
++	    d += (b2 ^ b) * (b2 ^ b);
++	    
++	    if(d < min) {
++		clut->ilut[i] = j;
++		min = d;
++	    }
++	}
++    }
++    
++    return clut;
++}
++
++static const char * _visualClass[] = {
++    "StaticGray",
++    "GrayScale",
++    "StaticColor",
++    "PseudoColor",
++    "TrueColor",
++    "DirectColor"
++};
++
++
++static void _print_visual(Visual *v) {
++    printf("Visual: class=%s, bpRGB=%i, CM=%i, r=%lx, g=%lx, b=%lx\n",
++	   _visualClass[v->class],
++	   v->bits_per_rgb,
++	   v->map_entries,
++	   v->red_mask, v->green_mask, v->blue_mask);
++}
++
++#if 0
++static void _print_ximage(XImage *x) {
++    const char * format[] = { "XYBitmap", "XYPixmap", "ZPixmap" };
++    printf("XImage: size=(%i,%i), xoffset=%i, format=%s, depth=%i, bpp=%i, stride=%i\n        r=%lx, g=%lx, b=%lx, unit=%i, pad=%i\n",
++	   x->width,
++	   x->height,
++	   x->xoffset,
++	   format[x->format],
++	   x->depth,
++	   x->bits_per_pixel,
++	   x->bytes_per_line,
++	   x->red_mask, x->green_mask, x->blue_mask,
++	   x->bitmap_unit, x->bitmap_pad);
++}
++
++
++const char * _cairoFormats[] = { "ARGB32", "RGB24", "A8", "A1" };
++
++static void _print_cairoimage(cairo_image_surface_t *i) {
++    
++    printf("CairoImage: size=(%i,%i), format=%s, depth=%i, stride=%i\n",
++	   i->width,
++	   i->height,
++	   _cairoFormats[i->format],
++	   i->depth,
++	   i->stride);
++}
++
++static void _print_cairomasks(cairo_format_masks_t *m) {
++    printf("CairoFormatMask: bpp=%i, a=%lx, r=%lx, g=%lx, b=%lx\n",
++	   m->bpp, m->alpha_mask, m->red_mask, m->green_mask, m->blue_mask);
++}
++#endif
++
+ static cairo_status_t
+ _get_image_surface (cairo_xlib_surface_t   *surface,
+ 		    cairo_rectangle_t      *interest_rect,
+@@ -508,7 +667,7 @@ _get_image_surface (cairo_xlib_surface_t
+ 
+ 	XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
+ 		   x1, y1, x2 - x1, y2 - y1, 0, 0);
+-	
++
+ 	ximage = XGetImage (surface->dpy,
+ 			    pixmap,
+ 			    0, 0,
+@@ -521,7 +680,7 @@ _get_image_surface (cairo_xlib_surface_t
+ 	return CAIRO_STATUS_NO_MEMORY;
+ 
+     _swap_ximage_to_native (ximage);
+-					
++
+     /*
+      * Compute the pixel format masks from either a visual or a 
+      * XRenderFormat, failing we assume the drawable is an
+@@ -569,20 +728,78 @@ _get_image_surface (cairo_xlib_surface_t
+     }
+     else
+     {
+-	/* 
+-	 * XXX This can't work.  We must convert the data to one of the 
+-	 * supported pixman formats.  Pixman needs another function
+-	 * which takes data in an arbitrary format and converts it
+-	 * to something supported by that library.
++	/*
++	 * Otherwise, we construct a buffer containing RGB24 data.
+ 	 */
++	unsigned char *data, *dst, *src, *col, *clut;
++	unsigned int stride;
++	int i,j;
++	
++	if(surface->visual == NULL) {
++	    printf("No visual for surface\n");
++	    goto FAIL;
++	}
++	stride = ximage->width * 4;
++	data = malloc(stride * ximage->height);
++	if(data == NULL) {
++	    printf("Cannot allocate RGB buffer\n");
++	    goto FAIL;
++	}
++	
++	switch (surface->visual->class) {
++	case StaticGray:
++	case GrayScale:
++	    for(j = 0; j < ximage->height; j++) {
++		src = (unsigned char *) ximage->data + ximage->bytes_per_line * j;
++		dst = data + j * stride;
++		for(i = 0; i < ximage->width; i++) {
++		    dst[1] = dst[2] = dst[3] = *src;
++		    dst += 4;
++		    src++;
++		}
++	    }
++	    break;
++	case PseudoColor:
++	case StaticColor:
++	    if(surface->clut == NULL) {
++		surface->clut = _get_clut_r3g3b2(
++		    surface->dpy,
++		    DefaultColormapOfScreen(surface->screen));
++	    }
++	    if(surface->clut == NULL) {
++		printf("Cannot allocate clut/ilut!\n");
++		free(data);
++		goto FAIL;
++	    }
++	    clut = surface->clut->clut;
++	    src = (unsigned char *) ximage->data;
++	    for(j = 0; j < ximage->height; j++) {
++		dst = data + j * stride;
++		for(i = 0; i < ximage->width; i++) {
++		    col = clut + (src[i] * 3);
++		    dst[1] = col[0];
++		    dst[2] = col[1];
++		    dst[3] = col[2];
++		    dst += 4;
++		}
++		src += ximage->bytes_per_line;
++	    }
++	    break;
++	default:
++	    printf("Dunno what to do with: ");
++	    _print_visual(surface->visual);
++	    goto FAIL;
++	}
++	free(ximage->data);
+ 	image = (cairo_image_surface_t*)
+-	    _cairo_image_surface_create_with_masks ((unsigned char *) ximage->data,
+-						    &masks,
+-						    ximage->width, 
+-						    ximage->height,
+-						    ximage->bytes_per_line);
+-	if (image->base.status)
++	    cairo_image_surface_create_for_data(data, CAIRO_FORMAT_RGB24, ximage->width, ximage->height, stride);
++	
++	if (image->base.status) {
++	    printf("Failed!\n");
++	    free(data);
+ 	    goto FAIL;
++	}
++	
+     }
+ 
+     /* Let the surface take ownership of the data */
+@@ -661,23 +878,67 @@ _draw_image_surface (cairo_xlib_surface_
+ 		     int                    dst_x,
+ 		     int                    dst_y)
+ {
++    static unsigned char *buf = NULL;
++    static int size = 0;
+     XImage ximage;
+-    int bpp, alpha, red, green, blue;
++    int bpp, alpha, red, green, blue, stride, depth, i, j, l;
++    unsigned char *data, *c, *d, *ilut;
+     int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
+     
+     pixman_format_get_masks (pixman_image_get_format (image->pixman_image),
+ 			     &bpp, &alpha, &red, &green, &blue);
+     
++    stride = image->width * 4;
++    depth = image->depth;
++    data = image->data;
++    l = 0;
++    
++    if(image->depth == 24 && surface->clut) {
++	stride = image->width;
++	if(stride%4)
++	    stride += 4 - stride % 4;
++	l = (stride * image->height);
++	if (size < l) {
++	    if(buf)
++		data = realloc(buf, l);
++	    else
++		data = malloc(l);
++	    if(data) {
++		buf = data;
++		size = l;
++	    }
++	} else {
++	    data = buf;
++	}
++	if(data == NULL)
++	    return CAIRO_STATUS_NO_MEMORY;
++	
++	ilut = surface->clut->ilut;
++	for(j=0;j<image->height;j++) {
++	    c = image->data + j * image->stride;
++	    d = data + j * stride;
++	    for(i=0;i<image->width;i++) {
++		d[i] = ilut[ (unsigned int)
++			     (((c[1]) & ( 0x7 << 5 )) |
++			      ((c[2] >> 3) & (0x7 << 2 )) |
++			      ((c[3] >> 6) & 0x3)) ];
++		c += 4;
++	    }
++	}
++	alpha = red = green = blue = 0;
++	depth = bpp = 8;
++    }
++
+     ximage.width = image->width;
+     ximage.height = image->height;
+     ximage.format = ZPixmap;
+-    ximage.data = (char *)image->data;
++    ximage.data = data;
+     ximage.byte_order = native_byte_order;
+-    ximage.bitmap_unit = 32;	/* always for libpixman */
++    ximage.bitmap_unit = 32; /* always for libpixman */
+     ximage.bitmap_bit_order = native_byte_order;
+-    ximage.bitmap_pad = 32;	/* always for libpixman */
+-    ximage.depth = image->depth;
+-    ximage.bytes_per_line = image->stride;
++    ximage.bitmap_pad = 32; /* always for libpixman */
++    ximage.depth = depth;
++    ximage.bytes_per_line = stride;
+     ximage.bits_per_pixel = bpp;
+     ximage.red_mask = red;
+     ximage.green_mask = green;
+@@ -685,7 +946,7 @@ _draw_image_surface (cairo_xlib_surface_
+     ximage.xoffset = 0;
+ 
+     XInitImage (&ximage);
+-    
++
+     _cairo_xlib_surface_ensure_gc (surface);
+     XPutImage(surface->dpy, surface->drawable, surface->gc,
+ 	      &ximage, 0, 0, dst_x, dst_y,
+@@ -1788,6 +2049,8 @@ _cairo_xlib_surface_create_internal (Dis
+     surface->have_clip_rects = FALSE;
+     surface->clip_rects = NULL;
+     surface->num_clip_rects = 0;
++
++    surface->clut = NULL;
+ 
+     return (cairo_surface_t *) surface;
+ }

Reply via email to