Blame contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-drawable.c

Packit a4058c
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Packit a4058c
/* GdkPixbuf library - convert X drawable information to RGB
Packit a4058c
 *
Packit a4058c
 * Copyright (C) 1999 Michael Zucchi
Packit a4058c
 *
Packit a4058c
 * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
Packit a4058c
 *          Cody Russell <bratsche@dfw.net>
Packit a4058c
 * 	    Federico Mena-Quintero <federico@gimp.org>
Packit a4058c
 *
Packit a4058c
 * This library is free software; you can redistribute it and/or
Packit a4058c
 * modify it under the terms of the GNU Library General Public
Packit a4058c
 * License as published by the Free Software Foundation; either
Packit a4058c
 * version 2 of the License, or (at your option) any later version.
Packit a4058c
 *
Packit a4058c
 * This library is distributed in the hope that it will be useful,
Packit a4058c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4058c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4058c
 * Library General Public License for more details.
Packit a4058c
 *
Packit a4058c
 * You should have received a copy of the GNU Library General Public
Packit a4058c
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit a4058c
 */
Packit a4058c
Packit a4058c
/* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */
Packit a4058c
Packit a4058c
Packit a4058c
#include "config.h"
Packit a4058c
#include <stdio.h>
Packit a4058c
#include <string.h>
Packit a4058c
#include "gdk-pixbuf-xlib-private.h"
Packit a4058c
#include <X11/Xlib.h>
Packit a4058c
#include <X11/Xutil.h>
Packit a4058c
Packit a4058c
/**
Packit a4058c
 * SECTION:gdk-pixbuf-xlib-from-drawables
Packit a4058c
 * @Short_description: Getting parts of an X drawable's image data into a pixbuf.
Packit a4058c
 * @Title: X Drawables to Pixbufs
Packit a4058c
 * 
Packit a4058c
 * The functions in this section allow you to take the image data
Packit a4058c
 * from an X drawable and dump it into a #GdkPixbuf.  This can be
Packit a4058c
 * used for screenshots and other special effects.  Note that these
Packit a4058c
 * operations can be expensive, since the image data has to be
Packit a4058c
 * transferred from the X server to the client program and converted.
Packit a4058c
 * 
Packit a4058c
 * 
Packit a4058c
 * These functions are analogous to those for the GDK version of
Packit a4058c
 * &gdk-pixbuf;.
Packit a4058c
 */
Packit a4058c
Packit a4058c
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
Packit a4058c
#define LITTLE
Packit a4058c
#endif
Packit a4058c
#define d(x)
Packit a4058c
Packit a4058c

Packit a4058c
Packit a4058c
static const guint32 mask_table[] = {
Packit a4058c
	0x00000000, 0x00000001, 0x00000003, 0x00000007,
Packit a4058c
	0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
Packit a4058c
	0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
Packit a4058c
	0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
Packit a4058c
	0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
Packit a4058c
	0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
Packit a4058c
	0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
Packit a4058c
	0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
Packit a4058c
	0xffffffff
Packit a4058c
};
Packit a4058c
Packit a4058c

Packit a4058c
/* color handling */
Packit a4058c
Packit a4058c
typedef struct xlib_colormap_struct xlib_colormap;
Packit a4058c
struct xlib_colormap_struct {
Packit a4058c
	int size;
Packit a4058c
	XColor *colors;
Packit a4058c
	Visual *visual;
Packit a4058c
	Colormap colormap;
Packit a4058c
};
Packit a4058c
Packit a4058c
static xlib_colormap *
Packit a4058c
xlib_get_colormap (Colormap id, Visual *visual)
Packit a4058c
{
Packit a4058c
	int i;
Packit a4058c
	xlib_colormap *xc = g_new (xlib_colormap, 1);
Packit a4058c
Packit a4058c
	xc->size = visual->map_entries;
Packit a4058c
	xc->colors = g_new (XColor, xc->size);
Packit a4058c
	xc->visual = visual;
Packit a4058c
	xc->colormap = id;
Packit a4058c
Packit a4058c
	for (i = 0; i < xc->size; i++) {
Packit a4058c
		xc->colors[i].pixel = i;
Packit a4058c
		xc->colors[i].flags = DoRed | DoGreen | DoBlue;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	XQueryColors (gdk_pixbuf_dpy, xc->colormap, xc->colors, xc->size);
Packit a4058c
Packit a4058c
	return xc;
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
xlib_colormap_free (xlib_colormap *xc)
Packit a4058c
{
Packit a4058c
	g_free (xc->colors);
Packit a4058c
	g_free (xc);
Packit a4058c
}
Packit a4058c
Packit a4058c
/* from gdkvisual.c */
Packit a4058c
static void
Packit a4058c
visual_decompose_mask (gulong  mask,
Packit a4058c
		       gint   *shift,
Packit a4058c
		       gint   *prec)
Packit a4058c
{
Packit a4058c
	*shift = 0;
Packit a4058c
	*prec = 0;
Packit a4058c
Packit a4058c
	while (!(mask & 0x1)) {
Packit a4058c
		(*shift)++;
Packit a4058c
		mask >>= 1;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	while (mask & 0x1) {
Packit a4058c
		(*prec)++;
Packit a4058c
		mask >>= 1;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean x_error;
Packit a4058c
Packit a4058c
static int
Packit a4058c
handle_x_error (Display *dpy, XErrorEvent *ev)
Packit a4058c
{
Packit a4058c
	x_error = TRUE;
Packit a4058c
	return 0;
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean
Packit a4058c
drawable_is_pixmap (Drawable d)
Packit a4058c
{
Packit a4058c
	/* copied from Imlib */
Packit a4058c
Packit a4058c
	XErrorHandler errh;
Packit a4058c
	XWindowAttributes wa;
Packit a4058c
	gboolean is_pixmap;
Packit a4058c
Packit a4058c
	errh = XSetErrorHandler (handle_x_error);
Packit a4058c
	x_error = FALSE;
Packit a4058c
	XGetWindowAttributes (gdk_pixbuf_dpy, d, &wa;;
Packit a4058c
	XSync (gdk_pixbuf_dpy, False);
Packit a4058c
	is_pixmap = x_error;
Packit a4058c
	XSetErrorHandler (errh);
Packit a4058c
Packit a4058c
	return is_pixmap;
Packit a4058c
}
Packit a4058c
Packit a4058c

Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 1 bits-pixel data
Packit a4058c
  no alpha
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
	register guint8 data;
Packit a4058c
	guint8 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	d (printf ("1 bits/pixel\n"));
Packit a4058c
Packit a4058c
	/* convert upto 8 pixels/time */
Packit a4058c
	/* its probably not worth trying to make this run very fast, who uses
Packit a4058c
	   1 bit displays anymore? */
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		o = orow;
Packit a4058c
Packit a4058c
		for (xx = 0; xx < width; xx ++) {
Packit a4058c
			data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
Packit a4058c
			*o++ = colormap->colors[data].red;
Packit a4058c
			*o++ = colormap->colors[data].green;
Packit a4058c
			*o++ = colormap->colors[data].blue;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 1 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
	register guint8 data;
Packit a4058c
	guint8 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	guint32 remap[2];
Packit a4058c
Packit a4058c
	d (printf ("1 bits/pixel\n"));
Packit a4058c
Packit a4058c
	/* convert upto 8 pixels/time */
Packit a4058c
	/* its probably not worth trying to make this run very fast, who uses
Packit a4058c
	   1 bit displays anymore? */
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (xx = 0; xx < 2; xx++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		remap[xx] = 0xff000000
Packit a4058c
			| colormap->colors[xx].blue << 16
Packit a4058c
			| colormap->colors[xx].green << 8
Packit a4058c
			| colormap->colors[xx].red;
Packit a4058c
#else
Packit a4058c
		remap[xx] = 0xff
Packit a4058c
			| colormap->colors[xx].red << 24
Packit a4058c
			| colormap->colors[xx].green << 16
Packit a4058c
			| colormap->colors[xx].blue << 8;
Packit a4058c
#endif
Packit a4058c
	}
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		o = orow;
Packit a4058c
Packit a4058c
		for (xx = 0; xx < width; xx ++) {
Packit a4058c
			data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
Packit a4058c
			*o++ = remap[data];
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 8 bits/pixel data
Packit a4058c
  no alpha
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
	guint32 mask;
Packit a4058c
	register guint32 data;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	register guint8 *s;
Packit a4058c
	register guint8 *o;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	d (printf ("8 bit, no alpha output\n"));
Packit a4058c
Packit a4058c
	mask = mask_table[image->depth];
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			data = *s++ & mask;
Packit a4058c
			*o++ = colormap->colors[data].red;
Packit a4058c
			*o++ = colormap->colors[data].green;
Packit a4058c
			*o++ = colormap->colors[data].blue;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 8 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
	guint32 mask;
Packit a4058c
	register guint32 data;
Packit a4058c
	guint32 remap[256];
Packit a4058c
	register guint8 *s;	/* read 2 pixels at once */
Packit a4058c
	register guint32 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	d (printf ("8 bit, with alpha output\n"));
Packit a4058c
Packit a4058c
	mask = mask_table[image->depth];
Packit a4058c
Packit a4058c
	for (xx = 0; xx < colormap->size; xx++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		remap[xx] = 0xff000000
Packit a4058c
			| colormap->colors[xx].blue << 16
Packit a4058c
			| colormap->colors[xx].green << 8
Packit a4058c
			| colormap->colors[xx].red;
Packit a4058c
#else
Packit a4058c
		remap[xx] = 0xff
Packit a4058c
			| colormap->colors[xx].red << 24
Packit a4058c
			| colormap->colors[xx].green << 16
Packit a4058c
			| colormap->colors[xx].blue << 8;
Packit a4058c
#endif
Packit a4058c
	}
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = (guint32 *) orow;
Packit a4058c
		for (xx = 0; xx < width; xx ++) {
Packit a4058c
			data = *s++ & mask;
Packit a4058c
			*o++ = remap[data];
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 16 bits/pixel data
Packit a4058c
  no alpha
Packit a4058c
  data in lsb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint32 *s;	/* read 2 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint8 *s;	/* read 2 pixels at once */
Packit a4058c
#endif
Packit a4058c
	register guint16 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = (guint32 *) srow;
Packit a4058c
#else
Packit a4058c
		s = srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint16 *) orow;
Packit a4058c
		for (xx = 1; xx < width; xx += 2) {
Packit a4058c
			register guint32 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
Packit a4058c
				| (data & 0x7e0) << 5 | (data & 0x600) >> 1;
Packit a4058c
			*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
Packit a4058c
				| (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
Packit a4058c
			*o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
Packit a4058c
				| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
Packit a4058c
#else
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
Packit a4058c
			s += 4;
Packit a4058c
			*o++ = (data & 0xf800) | (data & 0xe000) >> 5
Packit a4058c
				| (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
Packit a4058c
			*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
Packit a4058c
			*o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
Packit a4058c
				| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		/* check for last remaining pixel */
Packit a4058c
		if (width & 1) {
Packit a4058c
			register guint16 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *((short *) s);
Packit a4058c
#else
Packit a4058c
			data = *((short *) s);
Packit a4058c
			data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
Packit a4058c
#endif
Packit a4058c
			((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
Packit a4058c
			((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
Packit a4058c
			((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 16 bits/pixel data
Packit a4058c
  no alpha
Packit a4058c
  data in msb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint8 *s;	/* need to swap data order */
Packit a4058c
#else
Packit a4058c
	register guint32 *s;	/* read 2 pixels at once */
Packit a4058c
#endif
Packit a4058c
	register guint16 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = srow;
Packit a4058c
#else
Packit a4058c
		s = (guint32 *) srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint16 *) orow;
Packit a4058c
		for (xx = 1; xx < width; xx += 2) {
Packit a4058c
			register guint32 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
Packit a4058c
			s += 4;
Packit a4058c
			*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
Packit a4058c
				| (data & 0x7e0) << 5 | (data & 0x600) >> 1;
Packit a4058c
			*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
Packit a4058c
				| (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
Packit a4058c
			*o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
Packit a4058c
				| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
Packit a4058c
#else
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0xf800) | (data & 0xe000) >> 5
Packit a4058c
				| (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
Packit a4058c
			*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
Packit a4058c
			*o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
Packit a4058c
				| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		/* check for last remaining pixel */
Packit a4058c
		if (width & 1) {
Packit a4058c
			register guint16 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *((short *) s);
Packit a4058c
			data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
Packit a4058c
#else
Packit a4058c
			data = *((short *) s);
Packit a4058c
#endif
Packit a4058c
			((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
Packit a4058c
			((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
Packit a4058c
			((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 16 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
  data in lsb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint16 *s;	/* read 1 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint8 *s;
Packit a4058c
#endif
Packit a4058c
	register guint32 *o;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = (guint16 *) srow;
Packit a4058c
#else
Packit a4058c
		s = (guint8 *) srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint32 *) orow;
Packit a4058c
		for (xx = 0; xx < width; xx ++) {
Packit a4058c
			register guint32 data;
Packit a4058c
			/*  rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */
Packit a4058c
			/*  little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
Packit a4058c
				| (data & 0x7e0) << 5 | (data & 0x600) >> 1
Packit a4058c
				| (data & 0x1f) << 19 | (data & 0x1c) << 14
Packit a4058c
				| 0xff000000;
Packit a4058c
#else
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[0] | s[1] << 8;
Packit a4058c
			s += 2;
Packit a4058c
			*o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
Packit a4058c
				| (data & 0x7e0) << 13 | (data & 0x600) << 7
Packit a4058c
				| (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| 0xff;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 16 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
  data in msb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint8 *s;
Packit a4058c
#else
Packit a4058c
	register guint16 *s;	/* read 1 pixels at once */
Packit a4058c
#endif
Packit a4058c
	register guint32 *o;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = srow;
Packit a4058c
#else
Packit a4058c
		s = (guint16 *) srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint32 *) orow;
Packit a4058c
		for (xx = 0; xx < width; xx ++) {
Packit a4058c
			register guint32 data;
Packit a4058c
			/*  rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */
Packit a4058c
			/*  little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */
Packit a4058c
#ifdef LITTLE
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[0] | s[1] << 8;
Packit a4058c
			s += 2;
Packit a4058c
			*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
Packit a4058c
				| (data & 0x7e0) << 5 | (data & 0x600) >> 1
Packit a4058c
				| (data & 0x1f) << 19 | (data & 0x1c) << 14
Packit a4058c
				| 0xff000000;
Packit a4058c
#else
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
Packit a4058c
				| (data & 0x7e0) << 13 | (data & 0x600) << 7
Packit a4058c
				| (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| 0xff;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 15 bits/pixel data
Packit a4058c
  no alpha
Packit a4058c
  data in lsb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint32 *s;	/* read 2 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint8 *s;	/* read 2 pixels at once */
Packit a4058c
#endif
Packit a4058c
	register guint16 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = (guint32 *) srow;
Packit a4058c
#else
Packit a4058c
		s = srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint16 *) orow;
Packit a4058c
		for (xx = 1; xx < width; xx += 2) {
Packit a4058c
			register guint32 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
Packit a4058c
				| (data & 0x3e0) << 6 | (data & 0x380) << 1;
Packit a4058c
			*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
Packit a4058c
				| (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
Packit a4058c
			*o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
Packit a4058c
				| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
Packit a4058c
#else
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
Packit a4058c
			s += 4;
Packit a4058c
			*o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
Packit a4058c
				| (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
Packit a4058c
			*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
Packit a4058c
			*o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
Packit a4058c
				| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		/* check for last remaining pixel */
Packit a4058c
		if (width & 1) {
Packit a4058c
			register guint16 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *((short *) s);
Packit a4058c
#else
Packit a4058c
			data = *((short *) s);
Packit a4058c
			data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
Packit a4058c
#endif
Packit a4058c
			((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
Packit a4058c
			((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
Packit a4058c
			((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 15 bits/pixel data
Packit a4058c
  no alpha
Packit a4058c
  data in msb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint8 *s;	/* read 2 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint32 *s;	/* read 2 pixels at once */
Packit a4058c
#endif
Packit a4058c
	register guint16 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = srow;
Packit a4058c
#else
Packit a4058c
		s = (guint32 *) srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint16 *) orow;
Packit a4058c
		for (xx = 1; xx < width; xx += 2) {
Packit a4058c
			register guint32 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
Packit a4058c
			s += 4;
Packit a4058c
			*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
Packit a4058c
				| (data & 0x3e0) << 6 | (data & 0x380) << 1;
Packit a4058c
			*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
Packit a4058c
				| (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
Packit a4058c
			*o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
Packit a4058c
				| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
Packit a4058c
#else
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
Packit a4058c
				| (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
Packit a4058c
			*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
Packit a4058c
			*o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
Packit a4058c
				| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		/* check for last remaining pixel */
Packit a4058c
		if (width & 1) {
Packit a4058c
			register guint16 data;
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *((short *) s);
Packit a4058c
			data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
Packit a4058c
#else
Packit a4058c
			data = *((short *) s);
Packit a4058c
#endif
Packit a4058c
			((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
Packit a4058c
			((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
Packit a4058c
			((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 15 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
  data in lsb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint16 *s;	/* read 1 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint8 *s;
Packit a4058c
#endif
Packit a4058c
	register guint32 *o;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = (guint16 *) srow;
Packit a4058c
#else
Packit a4058c
		s = srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint32 *) orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			register guint32 data;
Packit a4058c
			/*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
Packit a4058c
			/*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
Packit a4058c
#ifdef LITTLE
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
Packit a4058c
				| (data & 0x3e0) << 6 | (data & 0x380) << 1
Packit a4058c
				| (data & 0x1f) << 19 | (data & 0x1c) << 14
Packit a4058c
				| 0xff000000;
Packit a4058c
#else
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[0] | s[1] << 8;
Packit a4058c
			s += 2;
Packit a4058c
			*o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
Packit a4058c
				| (data & 0x3e0) << 14 | (data & 0x380) << 9
Packit a4058c
				| (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| 0xff;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  convert 15 bits/pixel data
Packit a4058c
  with alpha
Packit a4058c
  data in msb format
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
#ifdef LITTLE
Packit a4058c
	register guint16 *s;	/* read 1 pixels at once */
Packit a4058c
#else
Packit a4058c
	register guint8 *s;
Packit a4058c
#endif
Packit a4058c
	register guint32 *o;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
#ifdef LITTLE
Packit a4058c
		s = (guint16 *) srow;
Packit a4058c
#else
Packit a4058c
		s = srow;
Packit a4058c
#endif
Packit a4058c
		o = (guint32 *) orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			register guint32 data;
Packit a4058c
			/*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
Packit a4058c
			/*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
Packit a4058c
#ifdef LITTLE
Packit a4058c
			/* swap endianness first */
Packit a4058c
			data = s[0] | s[1] << 8;
Packit a4058c
			s += 2;
Packit a4058c
			*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
Packit a4058c
				| (data & 0x3e0) << 6 | (data & 0x380) << 1
Packit a4058c
				| (data & 0x1f) << 19 | (data & 0x1c) << 14
Packit a4058c
				| 0xff000000;
Packit a4058c
#else
Packit a4058c
			data = *s++;
Packit a4058c
			*o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
Packit a4058c
				| (data & 0x3e0) << 14 | (data & 0x380) << 9
Packit a4058c
				| (data & 0x1f) << 11 | (data & 0x1c) << 6
Packit a4058c
				| 0xff;
Packit a4058c
#endif
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
Packit a4058c
static void
Packit a4058c
rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
	guint8 *s;	/* for byte order swapping */
Packit a4058c
	guint8 *o;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	d (printf ("32 bits/pixel with alpha\n"));
Packit a4058c
Packit a4058c
	/* lsb data */
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			*o++ = s[2];
Packit a4058c
			*o++ = s[1];
Packit a4058c
			*o++ = s[0];
Packit a4058c
			*o++ = 0xff;
Packit a4058c
			s += 4;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	guint8 *o, *s;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	d (printf ("32 bit, lsb, no alpha\n"));
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			*o++ = s[2];
Packit a4058c
			*o++ = s[1];
Packit a4058c
			*o++ = s[0];
Packit a4058c
			s += 4;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	guint8 *s;	/* for byte order swapping */
Packit a4058c
	guint8 *o;
Packit a4058c
Packit a4058c
	d (printf ("32 bit, msb, with alpha\n"));
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	/* msb data */
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			*o++ = s[1];
Packit a4058c
			*o++ = s[2];
Packit a4058c
			*o++ = s[3];
Packit a4058c
			*o++ = 0xff;
Packit a4058c
			s += 4;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
static void
Packit a4058c
rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	guint8 *s;
Packit a4058c
	guint8 *o;
Packit a4058c
Packit a4058c
	d (printf ("32 bit, msb, no alpha\n"));
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		s = srow;
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			*o++ = s[1];
Packit a4058c
			*o++ = s[2];
Packit a4058c
			*o++ = s[3];
Packit a4058c
			s += 4;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
/*
Packit a4058c
  This should work correctly with any display/any endianness, but will probably
Packit a4058c
  run quite slow
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha)
Packit a4058c
{
Packit a4058c
	int xx, yy;
Packit a4058c
	int width, height;
Packit a4058c
	int bpl;
Packit a4058c
	guint8 *srow = (guint8 *)image->data, *orow = pixels;
Packit a4058c
	guint8 *o;
Packit a4058c
	guint32 pixel;
Packit a4058c
	Visual *v;
Packit a4058c
	guint8 component;
Packit a4058c
	int i;
Packit a4058c
	int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec;
Packit a4058c
Packit a4058c
	width = image->width;
Packit a4058c
	height = image->height;
Packit a4058c
	bpl = image->bytes_per_line;
Packit a4058c
	v = cmap->visual;
Packit a4058c
Packit a4058c
	visual_decompose_mask (v->red_mask, &red_shift, &red_prec);
Packit a4058c
	visual_decompose_mask (v->green_mask, &green_shift, &green_prec);
Packit a4058c
	visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec);
Packit a4058c
Packit a4058c
	d(printf("rgb  mask/shift/prec = %x:%x:%x %d:%d:%d  %d:%d:%d\n",
Packit a4058c
		 v->red_mask, v->green_mask, v->blue_mask,
Packit a4058c
		 red_shift, green_shift, blue_shift,
Packit a4058c
		 red_prec, green_prec, blue_prec));
Packit a4058c
Packit a4058c
	for (yy = 0; yy < height; yy++) {
Packit a4058c
		o = orow;
Packit a4058c
		for (xx = 0; xx < width; xx++) {
Packit a4058c
			pixel = XGetPixel (image, xx, yy);
Packit a4058c
			switch (v->class) {
Packit a4058c
				/* I assume this is right for static & greyscale's too? */
Packit a4058c
			case StaticGray:
Packit a4058c
			case GrayScale:
Packit a4058c
			case StaticColor:
Packit a4058c
			case PseudoColor:
Packit a4058c
				*o++ = cmap->colors[pixel].red;
Packit a4058c
				*o++ = cmap->colors[pixel].green;
Packit a4058c
				*o++ = cmap->colors[pixel].blue;
Packit a4058c
				break;
Packit a4058c
			case TrueColor:
Packit a4058c
				/* This is odd because it must sometimes shift left (otherwise
Packit a4058c
				   I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic
Packit a4058c
				   should work for all bit sizes/shifts/etc. */
Packit a4058c
				component = 0;
Packit a4058c
				for (i = 24; i < 32; i += red_prec)
Packit a4058c
					component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i;
Packit a4058c
				*o++ = component;
Packit a4058c
				component = 0;
Packit a4058c
				for (i = 24; i < 32; i += green_prec)
Packit a4058c
					component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i;
Packit a4058c
				*o++ = component;
Packit a4058c
				component = 0;
Packit a4058c
				for (i = 24; i < 32; i += blue_prec)
Packit a4058c
					component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i;
Packit a4058c
				*o++ = component;
Packit a4058c
				break;
Packit a4058c
			case DirectColor:
Packit a4058c
				*o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red;
Packit a4058c
				*o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green;
Packit a4058c
				*o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue;
Packit a4058c
				break;
Packit a4058c
			}
Packit a4058c
			if (alpha)
Packit a4058c
				*o++ = 0xff;
Packit a4058c
		}
Packit a4058c
		srow += bpl;
Packit a4058c
		orow += rowstride;
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap);
Packit a4058c
Packit a4058c
static const cfunc convert_map[] = {
Packit a4058c
	rgb1,rgb1,rgb1a,rgb1a,
Packit a4058c
	rgb8,rgb8,rgb8a,rgb8a,
Packit a4058c
	rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
Packit a4058c
	rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
Packit a4058c
	rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
Packit a4058c
};
Packit a4058c
Packit a4058c
/*
Packit a4058c
  perform actual conversion
Packit a4058c
Packit a4058c
  If we can, try and use the optimised code versions, but as a default
Packit a4058c
  fallback, and always for direct colour, use the generic/slow but complete
Packit a4058c
  conversion function.
Packit a4058c
*/
Packit a4058c
static void
Packit a4058c
rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap)
Packit a4058c
{
Packit a4058c
	int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
Packit a4058c
	int bank=5;		/* default fallback converter */
Packit a4058c
	Visual *v = cmap->visual;
Packit a4058c
Packit a4058c
	d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
Packit a4058c
	d(printf("image depth = %d, bpp = %d\n", image->depth, image->bits_per_pixel));
Packit a4058c
Packit a4058c
	switch (v->class) {
Packit a4058c
				/* I assume this is right for static & greyscale's too? */
Packit a4058c
	case StaticGray:
Packit a4058c
	case GrayScale:
Packit a4058c
	case StaticColor:
Packit a4058c
	case PseudoColor:
Packit a4058c
		switch (image->bits_per_pixel) {
Packit a4058c
		case 1:
Packit a4058c
			bank = 0;
Packit a4058c
			break;
Packit a4058c
		case 8:
Packit a4058c
			bank = 1;
Packit a4058c
			break;
Packit a4058c
		}
Packit a4058c
		break;
Packit a4058c
	case TrueColor:
Packit a4058c
		switch (image->depth) {
Packit a4058c
		case 15:
Packit a4058c
			if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
Packit a4058c
			    && image->bits_per_pixel == 16)
Packit a4058c
				bank = 2;
Packit a4058c
			break;
Packit a4058c
		case 16:
Packit a4058c
			if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
Packit a4058c
			    && image->bits_per_pixel == 16)
Packit a4058c
				bank = 3;
Packit a4058c
			break;
Packit a4058c
		case 24:
Packit a4058c
		case 32:
Packit a4058c
			if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
Packit a4058c
			    && image->bits_per_pixel == 32)
Packit a4058c
				bank = 4;
Packit a4058c
			break;
Packit a4058c
		}
Packit a4058c
		break;
Packit a4058c
	case DirectColor:
Packit a4058c
		/* always use the slow version */
Packit a4058c
		break;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	d(printf("converting using conversion function in bank %d\n", bank));
Packit a4058c
Packit a4058c
	if (bank==5) {
Packit a4058c
		convert_real_slow(image, pixels, rowstride, cmap, alpha);
Packit a4058c
	} else {
Packit a4058c
		index |= bank << 2;
Packit a4058c
		(* convert_map[index]) (image, pixels, rowstride, cmap);
Packit a4058c
	}
Packit a4058c
}
Packit a4058c
Packit a4058c
static gboolean
Packit a4058c
xlib_window_is_viewable (Window w)
Packit a4058c
{
Packit a4058c
	XWindowAttributes wa;
Packit a4058c
Packit a4058c
	while (w != 0) {
Packit a4058c
		Window parent, root, *children;
Packit a4058c
		guint nchildren;
Packit a4058c
Packit a4058c
		XGetWindowAttributes (gdk_pixbuf_dpy, w, &wa;;
Packit a4058c
		if (wa.map_state != IsViewable)
Packit a4058c
			return FALSE;
Packit a4058c
Packit a4058c
		if (!XQueryTree (gdk_pixbuf_dpy, w, &root,
Packit a4058c
				 &parent, &children, &nchildren))
Packit a4058c
			return FALSE;
Packit a4058c
Packit a4058c
		if (nchildren > 0)
Packit a4058c
			XFree (children);
Packit a4058c
Packit a4058c
		if ((parent == root) || (w == root))
Packit a4058c
			return TRUE;
Packit a4058c
Packit a4058c
		w = parent;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	return FALSE;
Packit a4058c
}
Packit a4058c
Packit a4058c
static gint
Packit a4058c
xlib_window_get_origin (Window w, gint *x, gint *y)
Packit a4058c
{
Packit a4058c
	Window child;
Packit a4058c
	return XTranslateCoordinates (gdk_pixbuf_dpy, w,
Packit a4058c
				      RootWindow (gdk_pixbuf_dpy,
Packit a4058c
						  gdk_pixbuf_screen),
Packit a4058c
				      0, 0, x, y, &child);
Packit a4058c
}
Packit a4058c
Packit a4058c
/* Exported functions */
Packit a4058c
Packit a4058c
/**
Packit a4058c
 * gdk_pixbuf_xlib_get_from_drawable:
Packit a4058c
 * @dest: Destination pixbuf, or NULL if a new pixbuf should be created.
Packit a4058c
 * @src: Source drawable.
Packit a4058c
 * @cmap: A colormap if @src is a pixmap.  If it is a window, this argument will
Packit a4058c
 * be ignored.
Packit a4058c
 * @visual: A visual if @src is a pixmap.  If it is a window, this argument will
Packit a4058c
 * be ignored.
Packit a4058c
 * @src_x: Source X coordinate within drawable.
Packit a4058c
 * @src_y: Source Y coordinate within drawable.
Packit a4058c
 * @dest_x: Destination X coordinate in pixbuf, or 0 if @dest is NULL.
Packit a4058c
 * @dest_y: Destination Y coordinate in pixbuf, or 0 if @dest is NULL.
Packit a4058c
 * @width: Width in pixels of region to get.
Packit a4058c
 * @height: Height in pixels of region to get.
Packit a4058c
 *
Packit a4058c
 * Transfers image data from a Gdk drawable and converts it to an RGB(A)
Packit a4058c
 * representation inside a GdkPixbuf.
Packit a4058c
 *
Packit a4058c
 * If the drawable @src is a pixmap, then a suitable colormap must be specified,
Packit a4058c
 * since pixmaps are just blocks of pixel data without an associated colormap.
Packit a4058c
 * If the drawable is a window, the @cmap argument will be ignored and the
Packit a4058c
 * window's own colormap will be used instead.
Packit a4058c
 *
Packit a4058c
 * If the specified destination pixbuf @dest is #NULL, then this function will
Packit a4058c
 * create an RGB pixbuf with 8 bits per channel and no alpha, with the same size
Packit a4058c
 * specified by the @width and @height arguments.  In this case, the @dest_x and
Packit a4058c
 * @dest_y arguments must be specified as 0, otherwise the function will return
Packit a4058c
 * #NULL.  If the specified destination pixbuf is not NULL and it contains alpha
Packit a4058c
 * information, then the filled pixels will be set to full opacity.
Packit a4058c
 *
Packit a4058c
 * If the specified drawable is a pixmap, then the requested source rectangle
Packit a4058c
 * must be completely contained within the pixmap, otherwise the function will
Packit a4058c
 * return #NULL.
Packit a4058c
 *
Packit a4058c
 * If the specified drawable is a window, then it must be viewable, i.e. all of
Packit a4058c
 * its ancestors up to the root window must be mapped.  Also, the specified
Packit a4058c
 * source rectangle must be completely contained within the window and within
Packit a4058c
 * the screen.  If regions of the window are obscured by noninferior windows, the
Packit a4058c
 * contents of those regions are undefined.  The contents of regions obscured by
Packit a4058c
 * inferior windows of a different depth than that of the source window will also
Packit a4058c
 * be undefined.
Packit a4058c
 *
Packit a4058c
 * Return value: The same pixbuf as @dest if it was non-NULL, or a newly-created
Packit a4058c
 * pixbuf with a reference count of 1 if no destination pixbuf was specified; in
Packit a4058c
 * the latter case, NULL will be returned if not enough memory could be
Packit a4058c
 * allocated for the pixbuf to be created.
Packit a4058c
 **/
Packit a4058c
GdkPixbuf *
Packit a4058c
gdk_pixbuf_xlib_get_from_drawable (GdkPixbuf *dest,
Packit a4058c
				   Drawable src,
Packit a4058c
				   Colormap cmap, Visual *visual,
Packit a4058c
				   int src_x, int src_y,
Packit a4058c
				   int dest_x, int dest_y,
Packit a4058c
				   int width, int height)
Packit a4058c
{
Packit a4058c
	guint src_width, src_height;
Packit a4058c
	XImage *image;
Packit a4058c
	int rowstride, bpp, alpha;
Packit a4058c
	XWindowAttributes wa;
Packit a4058c
	xlib_colormap *x_cmap;
Packit a4058c
	gboolean is_pixmap;
Packit a4058c
Packit a4058c
	/* General sanity checks */
Packit a4058c
Packit a4058c
	g_return_val_if_fail (src != 0, NULL);
Packit a4058c
Packit a4058c
	is_pixmap = drawable_is_pixmap (src);
Packit a4058c
Packit a4058c
	if (is_pixmap) {
Packit a4058c
		g_return_val_if_fail (cmap != 0, NULL);
Packit a4058c
		g_return_val_if_fail (visual != NULL, NULL);
Packit a4058c
	}
Packit a4058c
	else
Packit a4058c
		g_return_val_if_fail (xlib_window_is_viewable (src), NULL);
Packit a4058c
Packit a4058c
	if (!dest)
Packit a4058c
		g_return_val_if_fail (dest_x == 0 && dest_y == 0, NULL);
Packit a4058c
	else {
Packit a4058c
		g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL);
Packit a4058c
		g_return_val_if_fail (gdk_pixbuf_get_n_channels (dest) == 3
Packit a4058c
				      || gdk_pixbuf_get_n_channels (dest) == 4, NULL);
Packit a4058c
		g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL);
Packit a4058c
	}
Packit a4058c
Packit a4058c
	/* Coordinate sanity checks */
Packit a4058c
Packit a4058c
	if (!is_pixmap) {
Packit a4058c
	    XGetWindowAttributes (gdk_pixbuf_dpy, src, &wa;;
Packit a4058c
	    src_width = wa.width;
Packit a4058c
	    src_height = wa.height;
Packit a4058c
	} else {
Packit a4058c
	    Window root;
Packit a4058c
	    int tx, ty;
Packit a4058c
	    guint bwidth, depth;
Packit a4058c
	    XGetGeometry (gdk_pixbuf_dpy, src, &root, &tx, &ty,
Packit a4058c
			  &src_width, &src_height, &bwidth, &depth);
Packit a4058c
	}
Packit a4058c
Packit a4058c
	g_return_val_if_fail (src_x >= 0 && src_y >= 0, NULL);
Packit a4058c
	g_return_val_if_fail (src_x + width <= src_width
Packit a4058c
			      && src_y + height <= src_height, NULL);
Packit a4058c
Packit a4058c
	if (dest) {
Packit a4058c
		g_return_val_if_fail (dest_x >= 0 && dest_y >= 0, NULL);
Packit a4058c
		g_return_val_if_fail (dest_x + width <= gdk_pixbuf_get_width (dest), NULL);
Packit a4058c
		g_return_val_if_fail (dest_y + height <= gdk_pixbuf_get_height (dest), NULL);
Packit a4058c
	}
Packit a4058c
Packit a4058c
	if (!is_pixmap) {
Packit a4058c
		int ret;
Packit a4058c
		int src_xorigin, src_yorigin;
Packit a4058c
		int screen_width, screen_height;
Packit a4058c
		int screen_srcx, screen_srcy;
Packit a4058c
Packit a4058c
		ret = xlib_window_get_origin (src, &src_xorigin, &src_yorigin);
Packit a4058c
		g_return_val_if_fail (ret != FALSE, NULL);
Packit a4058c
Packit a4058c
		screen_width = DisplayWidth (gdk_pixbuf_dpy, gdk_pixbuf_screen);
Packit a4058c
		screen_height = DisplayHeight (gdk_pixbuf_dpy, gdk_pixbuf_screen);
Packit a4058c
Packit a4058c
		screen_srcx = src_xorigin + src_x;
Packit a4058c
		screen_srcy = src_yorigin + src_y;
Packit a4058c
Packit a4058c
		g_return_val_if_fail (screen_srcx >= 0 && screen_srcy >= 0, NULL);
Packit a4058c
		g_return_val_if_fail (screen_srcx + width <= screen_width, NULL);
Packit a4058c
		g_return_val_if_fail (screen_srcy + height <= screen_height, NULL);
Packit a4058c
	}
Packit a4058c
Packit a4058c
	/* Get Image in ZPixmap format (packed bits). */
Packit a4058c
	image = XGetImage (gdk_pixbuf_dpy, src, src_x, src_y,
Packit a4058c
			   width, height, AllPlanes, ZPixmap);
Packit a4058c
	g_return_val_if_fail (image != NULL, NULL);
Packit a4058c
Packit a4058c
	/* Create the pixbuf if needed */
Packit a4058c
	if (!dest) {
Packit a4058c
		dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
Packit a4058c
				       FALSE, 8, width, height);
Packit a4058c
		if (!dest) {
Packit a4058c
			XDestroyImage (image);
Packit a4058c
			return NULL;
Packit a4058c
		}
Packit a4058c
	}
Packit a4058c
Packit a4058c
	/* Get the colormap if needed */
Packit a4058c
	if (!is_pixmap)
Packit a4058c
	{
Packit a4058c
		cmap = wa.colormap;
Packit a4058c
		visual = wa.visual;
Packit a4058c
	}
Packit a4058c
Packit a4058c
	x_cmap = xlib_get_colormap (cmap, visual);
Packit a4058c
Packit a4058c
	alpha = gdk_pixbuf_get_has_alpha (dest);
Packit a4058c
	rowstride = gdk_pixbuf_get_rowstride (dest);
Packit a4058c
	bpp = alpha ? 4 : 3;
Packit a4058c
Packit a4058c
	/* we offset into the image data based on the position we are retrieving from */
Packit a4058c
	rgbconvert (image, gdk_pixbuf_get_pixels (dest) +
Packit a4058c
		    (dest_y * rowstride) + (dest_x * bpp),
Packit a4058c
		    rowstride,
Packit a4058c
		    alpha,
Packit a4058c
		    x_cmap);
Packit a4058c
Packit a4058c
	xlib_colormap_free (x_cmap);
Packit a4058c
	XDestroyImage (image);
Packit a4058c
Packit a4058c
	return dest;
Packit a4058c
}