summaryrefslogtreecommitdiff
path: root/graphics/cairo
diff options
context:
space:
mode:
authordmcmahill <dmcmahill@pkgsrc.org>2006-08-31 11:12:58 +0000
committerdmcmahill <dmcmahill@pkgsrc.org>2006-08-31 11:12:58 +0000
commit238b22083755898e0ed564e13b63ce2318c33c71 (patch)
tree6dd13fb2cc43ca30a528fea2aa93684768106c34 /graphics/cairo
parent0f87b08ce2bbfb29c6f53eb155bf8ead1b460dc5 (diff)
downloadpkgsrc-238b22083755898e0ed564e13b63ce2318c33c71.tar.gz
Fix cairo on 8-bit psuedocolor displays. Finally I can use gtk again...
Diffstat (limited to 'graphics/cairo')
-rw-r--r--graphics/cairo/Makefile3
-rw-r--r--graphics/cairo/distinfo3
-rw-r--r--graphics/cairo/patches/patch-ae456
3 files changed, 460 insertions, 2 deletions
diff --git a/graphics/cairo/Makefile b/graphics/cairo/Makefile
index fea47f25c9f..387f055e861 100644
--- a/graphics/cairo/Makefile
+++ b/graphics/cairo/Makefile
@@ -1,6 +1,7 @@
-# $NetBSD: Makefile,v 1.45 2006/08/19 10:33:39 wiz Exp $
+# $NetBSD: Makefile,v 1.46 2006/08/31 11:12:58 dmcmahill Exp $
DISTNAME= cairo-1.2.4
+PKGREVISION= 1
CATEGORIES= graphics
MASTER_SITES= http://cairographics.org/releases/
diff --git a/graphics/cairo/distinfo b/graphics/cairo/distinfo
index bb9965ebd06..59b7a46f708 100644
--- a/graphics/cairo/distinfo
+++ b/graphics/cairo/distinfo
@@ -1,4 +1,4 @@
-$NetBSD: distinfo,v 1.22 2006/08/19 10:33:39 wiz Exp $
+$NetBSD: distinfo,v 1.23 2006/08/31 11:12:58 dmcmahill Exp $
SHA1 (cairo-1.2.4.tar.gz) = 5520b771c8b85acea78fa56fc4c39b4dca6bcc7c
RMD160 (cairo-1.2.4.tar.gz) = dee558b7489aa089de6963d909a8352725e10bdd
@@ -7,3 +7,4 @@ SHA1 (patch-aa) = 1b8ac1d495214c80b2e0ba28490bbc212f727773
SHA1 (patch-ab) = 14f3122cea953ad460b96cb2cf2347e5ed007450
SHA1 (patch-ac) = 71c66c051673a40b816c80cd8a67bfb4d0b6000b
SHA1 (patch-ad) = 60ebdcbbcd0a7bd97ba4d25e79500547008ede34
+SHA1 (patch-ae) = f1b3cd59532ae52457d0b6f8f97186d4a96eb0b4
diff --git a/graphics/cairo/patches/patch-ae b/graphics/cairo/patches/patch-ae
new file mode 100644
index 00000000000..4b2963fe1e3
--- /dev/null
+++ b/graphics/cairo/patches/patch-ae
@@ -0,0 +1,456 @@
+$NetBSD: patch-ae,v 1.3 2006/08/31 11:12:58 dmcmahill Exp $
+
+Adapted from:
+http://ekyo.nerim.net/software/patch-1.2.0-src_cairo-xlib-surface_c
+
+Fixes cairo on 8-bit psuedo color and other 8-bit displays.
+
+The patch listed above is for 1.2.0 and took some minor modification to
+apply to 1.2.4.
+
+--- src/cairo-xlib-surface.c.orig 2006-08-18 14:20:16.000000000 +0000
++++ src/cairo-xlib-surface.c 2006-08-31 10:53:10.000000000 +0000
+@@ -82,4 +82,6 @@
+ #define CAIRO_ASSUME_PIXMAP 20
+
++struct clut_r3g3b2;
++
+ struct _cairo_xlib_surface {
+ cairo_surface_t base;
+@@ -127,4 +129,7 @@
+
+ XRenderPictFormat *xrender_format;
++
++ struct clut_r3g3b2 *clut;
++ int workaround;
+ };
+
+@@ -505,4 +510,158 @@
+ }
+
++#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;
++ uint32_t clut[256];
++ 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 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 */
++ for (i = 0; i < 256; i++) {
++ XColor xcol;
++ xcol.pixel = i;
++ XQueryColor(dpy, cmap, &xcol);
++ clut->clut[i] = ( ( ((uint32_t)xcol.red & 0xff00 ) << 8) |
++ ( ((uint32_t)xcol.green & 0xff00 ) ) |
++ ( ((uint32_t)xcol.blue & 0xff00 ) >> 8) );
++ }
++ /*
++
++ 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++) {
++ r2 = (clut->clut[j] & 0xff0000) >> 21;
++ g2 = (clut->clut[j] & 0x00ff00) >> 13;
++ b2 = (clut->clut[j] & 0x0000ff) >> 5;
++ if ( r2 == r && g2 == g && (b2 & 0x6) == b ) {
++ clut->ilut[i] = j;
++ break;
++ }
++ /*
++ Squares 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
++
++#define WORKAROUND_NONE 0
++#define WORKAROUND_8BIT_GRAYLEVEL 1
++#define WORKAROUND_8BIT_PALETTE 2
++#if 1
++#define WORKAROUND_R5G6B5 3
++#endif
++
+ static cairo_status_t
+ _get_image_surface (cairo_xlib_surface_t *surface,
+@@ -659,17 +818,94 @@
+ {
+ /*
+- * 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
++ * using the specified workaround.
+ */
++ uint32_t *data, *dst, *clut;
++ uint8_t *src8;
++ uint16_t *src16;
++ int i,j;
++
++ if(surface->visual == NULL) {
++ printf("No visual for surface\n");
++ goto FAIL;
++ }
++
++ if (surface->workaround == WORKAROUND_NONE) {
++ printf("No workaround for this pixel format: ");
++ _print_visual(surface->visual);
++ goto FAIL;
++ }
++
++ data = (uint32_t*)malloc(ximage->height * ximage->width * 4);
++ if(data == NULL) {
++ printf("Cannot allocate RGB buffer\n");
++ goto FAIL;
++ }
++
++ switch (surface->workaround) {
++
++ case WORKAROUND_8BIT_GRAYLEVEL:
++
++ dst = data;
++ for(j = 0; j < ximage->height; j++) {
++ src8 = (uint8_t *) (ximage->data + ximage->bytes_per_line * j);
++ for(i = 0; i < ximage->width; i++) {
++ *dst++ = (*src8 << 16) | (*src8 << 8) | *src8;
++ src8++;
++ }
++ }
++ break;
++
++ case WORKAROUND_8BIT_PALETTE:
++
++ if(surface->clut == NULL) {
++ surface->clut = _get_clut_r3g3b2(
++ surface->dpy,
++ DefaultColormapOfScreen(surface->screen));
++ }
++
++ if(surface->clut == NULL) {
++ free(data);
++ goto FAIL;
++ }
++
++ clut = surface->clut->clut;
++ src8 = (uint8_t*) ximage->data;
++ dst = data;
++ for(j = 0; j < ximage->height; j++) {
++ for(i = 0; i < ximage->width; i++)
++ *dst++ = clut[src8[i]];
++ src8 += ximage->bytes_per_line;
++ }
++ break;
++#if 1
++ case WORKAROUND_R5G6B5:
++
++ src16 = (uint16_t*)ximage->data;
++ dst = data;
++ for(j = 0; j < ximage->height; j++) {
++ for(i = 0; i < ximage->width; i++) {
++ *dst++ = ( ( ((src16[i] & 0xf800) << 8) | ((src16[i] & 0xe000) << 3) ) |
++ ( ((src16[i] & 0x07e0) << 5) | ((src16[i] & 0x0600) >> 1) ) |
++ ( ((src16[i] & 0x001f) << 3) | ((src16[i] & 0x001f) >> 2) ) );
++ }
++ src16 += ximage->bytes_per_line / sizeof(*src16);
++ }
++ break;
++#endif
++ 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((unsigned char *)data, CAIRO_FORMAT_RGB24, ximage->width, ximage->height, ximage->width*4);
++
++ if (image->base.status) {
++ printf("Failed!\n");
++ free(data);
+ goto FAIL;
++ }
+ }
+
+@@ -744,4 +980,30 @@
+ }
+
++
++static int
++make_space_for(unsigned char ** buf, int *size, int *stride, int width, int height, int Bpp)
++{
++ unsigned char * data;
++ int l;
++
++ *stride = width * Bpp;
++ if(*stride%4)
++ *stride += 4 - *stride % 4;
++ l = (*stride * height);
++ if (*size < l) {
++ if(*buf)
++ data = realloc(*buf, l);
++ else
++ data = malloc(l);
++ if(data) {
++ *buf = data;
++ *size = l;
++ } else {
++ return -1;
++ }
++ }
++ return 0;
++}
++
+ static cairo_status_t
+ _draw_image_surface (cairo_xlib_surface_t *surface,
+@@ -750,6 +1012,12 @@
+ int dst_y)
+ {
++ static unsigned char *buf = NULL;
++ static int size = 0;
+ XImage ximage;
+- unsigned int bpp, alpha, red, green, blue;
++ unsigned int bpp, alpha, red, green, blue, stride, depth, i, j;
++ unsigned char *data, *ilut;
++ uint32_t *src;
++ uint8_t *dst8;
++ uint16_t *dst16;
+ int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
+
+@@ -757,14 +1025,87 @@
+ &bpp, &alpha, &red, &green, &blue);
+
++
++ switch(surface->workaround) {
++ case WORKAROUND_NONE:
++ /* Default behaviour is supposed to work */
++ stride = image->width * 4;
++ depth = image->depth;
++ data = image->data;
++ break;
++
++ case WORKAROUND_8BIT_GRAYLEVEL:
++
++ if (make_space_for(&buf, &size, &stride, image->width, image->height, 1))
++ return CAIRO_STATUS_NO_MEMORY;
++ data = buf;
++
++ for(j=0;j<image->height;j++) {
++ src = (uint32_t*)(image->data);
++ dst8 = data + j * stride;
++ for(i=0;i<image->width;i++) {
++ /* XXX use correct factor for each channel */
++ dst8[i] = ( ((*src >> 16) & 0xff) +
++ ((*src >> 8) & 0xff) +
++ (*src & 0xff) ) / 3;
++ src++;
++ }
++ }
++
++ alpha = red = green = blue = 0;
++ depth = bpp = 8;
++ break;
++
++ case WORKAROUND_8BIT_PALETTE:
++
++ if (make_space_for(&buf, &size, &stride, image->width, image->height, 1))
++ return CAIRO_STATUS_NO_MEMORY;
++ data = buf;
++ src = (uint32_t*)image->data;
++ ilut = surface->clut->ilut;
++ for(j=0;j<image->height;j++) {
++ dst8 = data + j * stride;
++ for(i=0;i<image->width;i++) {
++ dst8[i] = ilut[ ((*src >> 16) & 0xe0) |
++ ((*src >> 11) & 0x1c) |
++ ((*src >> 6) & 0x03) ];
++ src++;
++ }
++ }
++ alpha = red = green = blue = 0;
++ depth = bpp = 8;
++ break;
++
++ case WORKAROUND_R5G6B5:
++ if (make_space_for(&buf, &size, &stride, image->width, image->height, 2))
++ return CAIRO_STATUS_NO_MEMORY;
++ data = buf;
++ src = (uint32_t*)image->data;
++ for(j=0;j<image->height;j++) {
++ dst16 = (uint16_t*)(data + j * stride);
++ for(i=0;i<image->width;i++) {
++ dst16[i] = ( ((*src >> 8) & 0xf800) |
++ ((*src >> 5) & 0x07e0) |
++ ((*src >> 3) & 0x001f) );
++ src++;
++ }
++ }
++ alpha = 0; red = 0xf800; green = 0x07e0; blue = 0x001f;
++ depth = bpp = 16;
++ break;
++ }
++
+ ximage.width = image->width;
+ ximage.height = image->height;
+ ximage.format = ZPixmap;
+- ximage.data = (char *)image->data;
++ //ximage.data = (char *)image->data;
++ ximage.data = data;
+ ximage.byte_order = native_byte_order;
+ 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.depth = image->depth;
++ ximage.depth = depth;
++ //ximage.bytes_per_line = image->stride;
++ ximage.bytes_per_line = stride;
+ ximage.bits_per_pixel = bpp;
+ ximage.red_mask = red;
+@@ -1891,4 +2232,28 @@
+ surface->clip_rects = NULL;
+ surface->num_clip_rects = 0;
++ surface->clut = NULL;
++ surface->workaround = WORKAROUND_NONE;
++
++ if (surface->xrender_format == NULL) {
++ /* Install the correct workaround */
++ switch (visual->class) {
++ case StaticGray:
++ case GrayScale:
++ surface->workaround = WORKAROUND_8BIT_GRAYLEVEL;
++ break;
++ case PseudoColor:
++ case StaticColor:
++ surface->workaround = WORKAROUND_8BIT_PALETTE;
++ break;
++ case TrueColor:
++#if 1
++ if (visual->red_mask == 0xf800 &&
++ visual->green_mask == 0x07e0 &&
++ visual->blue_mask == 0x001f) {
++ surface->workaround = WORKAROUND_R5G6B5;
++ }
++#endif
++ }
++ }
+
+ return (cairo_surface_t *) surface;