diff -NurdB cairo-1.0.0/src/cairo-xlib-surface.c cairo-1.0.0-patched/src/cairo-xlib-surface.c --- cairo-1.0.0/src/cairo-xlib-surface.c 2005-08-24 00:42:19.000000000 -0500 +++ cairo-1.0.0-patched/src/cairo-xlib-surface.c 2005-09-02 10:12:59.000000000 -0500 @@ -60,6 +60,9 @@ static cairo_bool_t _cairo_surface_is_xlib (cairo_surface_t *surface); +static cairo_bool_t +_native_byte_order_lsb (void); + /* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will @@ -302,6 +305,116 @@ return False; } +static void +_swap_ximage_2bytes (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint16_t *p = (uint16_t *)line; + for (i = ximage->width; i; i--) { + *p = (((*p & 0x00ff) << 8) | + ((*p) >> 8)); + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_4bytes (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint32_t *p = (uint32_t *)line; + for (i = ximage->width; i; i--) { + *p = (((*p & 0x000000ff) << 24) | + ((*p & 0x0000ff00) << 8) | + ((*p & 0x00ff0000) >> 8) | + ((*p) >> 24)); + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_bits (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + int unit = ximage->bitmap_unit; + int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8; + + for (j = ximage->height; j; j--) { + char *p = line; + + for (i = line_bytes; i; i--) { + char b = *p; + b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); + b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); + b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); + *p = b; + + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_to_native (XImage *ximage) +{ + int unit_bytes = 0; + int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; + + if (ximage->bits_per_pixel == 1 && + ximage->bitmap_bit_order != native_byte_order) { + _swap_ximage_bits (ximage); + if (ximage->bitmap_bit_order == ximage->byte_order) + return; + } + + if (ximage->byte_order == native_byte_order) + return; + + switch (ximage->bits_per_pixel) { + case 1: + unit_bytes = ximage->bitmap_unit / 8; + break; + case 8: + case 16: + case 32: + unit_bytes = ximage->bits_per_pixel / 8; + break; + default: + /* This could be hit on some uncommon but possible cases, + * such as bpp=4. These are cases that libpixman can't deal + * with in any case. + */ + ASSERT_NOT_REACHED; + } + + switch (unit_bytes) { + case 1: + return; + case 2: + _swap_ximage_2bytes (ximage); + break; + case 4: + _swap_ximage_4bytes (ximage); + break; + default: + ASSERT_NOT_REACHED; + } +} + static cairo_status_t _get_image_surface (cairo_xlib_surface_t *surface, cairo_rectangle_t *interest_rect, @@ -405,6 +518,8 @@ } if (!ximage) return CAIRO_STATUS_NO_MEMORY; + + _swap_ximage_to_native (ximage); /* * Compute the pixel format masks from either a visual or a @@ -545,40 +660,35 @@ int dst_x, int dst_y) { - XImage *ximage; - unsigned bitmap_pad; - - /* XXX this is wrong */ - if (image->depth > 16) - bitmap_pad = 32; - else if (image->depth > 8) - bitmap_pad = 16; - else - bitmap_pad = 8; - - ximage = XCreateImage (surface->dpy, - DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)), - image->depth, - ZPixmap, - 0, - (char *) image->data, - image->width, - image->height, - bitmap_pad, - image->stride); - if (ximage == NULL) - return CAIRO_STATUS_NO_MEMORY; + XImage ximage; + int bpp, alpha, red, green, blue; + 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); + + ximage.width = image->width; + ximage.height = image->height; + ximage.format = ZPixmap; + ximage.data = (char *)image->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.bits_per_pixel = bpp; + ximage.red_mask = red; + ximage.green_mask = green; + ximage.blue_mask = blue; + XInitImage (&ximage); + _cairo_xlib_surface_ensure_gc (surface); XPutImage(surface->dpy, surface->drawable, surface->gc, - ximage, 0, 0, dst_x, dst_y, + &ximage, 0, 0, dst_x, dst_y, image->width, image->height); - /* Foolish XDestroyImage thinks it can free my data, but I won't - stand for it. */ - ximage->data = NULL; - XDestroyImage (ximage); - return CAIRO_STATUS_SUCCESS; }