[cairo-commit] cairo/src cairo-xlib-surface.c,1.118,1.118.2.1
Owen Taylor
commit at pdx.freedesktop.org
Wed Aug 31 15:09:46 PDT 2005
- Previous message: [cairo-commit] cairo ChangeLog,1.1026,1.1026.2.1
- Next message: [cairo-commit] cairo-perl Cairo.pm, 1.5, 1.6 ChangeLog, 1.12,
1.13 MANIFEST, 1.5, 1.6 Makefile.PL, 1.9, 1.10 NEWS, NONE,
1.1 README, 1.3, 1.4
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv7146/src
Modified Files:
Tag: BRANCH_1_0
cairo-xlib-surface.c
Log Message:
2005-08-31 Owen Taylor <otaylor at redhat.com>
* src/cairo-xlib-surface.c (_get_image_surface)
(_draw_image_surface): Handle displays which don't match
the local endianness by byteswapping on GetImage/PutImage.
(#4321, reported by Sjoerd Simons)
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.118
retrieving revision 1.118.2.1
diff -u -d -r1.118 -r1.118.2.1
--- cairo-xlib-surface.c 30 Aug 2005 17:50:27 -0000 1.118
+++ cairo-xlib-surface.c 31 Aug 2005 22:09:43 -0000 1.118.2.1
@@ -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;
}
- Previous message: [cairo-commit] cairo ChangeLog,1.1026,1.1026.2.1
- Next message: [cairo-commit] cairo-perl Cairo.pm, 1.5, 1.6 ChangeLog, 1.12,
1.13 MANIFEST, 1.5, 1.6 Makefile.PL, 1.9, 1.10 NEWS, NONE,
1.1 README, 1.3, 1.4
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list