diff options
author | dmcmahill <dmcmahill@pkgsrc.org> | 2006-08-31 11:12:58 +0000 |
---|---|---|
committer | dmcmahill <dmcmahill@pkgsrc.org> | 2006-08-31 11:12:58 +0000 |
commit | 238b22083755898e0ed564e13b63ce2318c33c71 (patch) | |
tree | 6dd13fb2cc43ca30a528fea2aa93684768106c34 /graphics/cairo | |
parent | 0f87b08ce2bbfb29c6f53eb155bf8ead1b460dc5 (diff) | |
download | pkgsrc-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/Makefile | 3 | ||||
-rw-r--r-- | graphics/cairo/distinfo | 3 | ||||
-rw-r--r-- | graphics/cairo/patches/patch-ae | 456 |
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; |