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; + }