Back to index

scribus-ng  1.3.4.dfsg+svn20071115
gdk-pixbuf-xlib-drawable.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
00002 /* GdkPixbuf library - convert X drawable information to RGB
00003  *
00004  * Copyright (C) 1999 Michael Zucchi
00005  *
00006  * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
00007  *          Cody Russell <bratsche@dfw.net>
00008  *         Federico Mena-Quintero <federico@gimp.org>
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this library; if not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023  * Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */
00027 
00028 
00029 #include "scconfig.h"
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include "gdk-pixbuf-xlib-private.h"
00033 #include <X11/Xlib.h>
00034 #include <X11/Xutil.h>
00035 
00036 #ifndef WORDS_BIGENDIAN
00037 #define LITTLE
00038 #endif
00039 
00040 #define d(x)
00041 
00042 
00043 
00044 static unsigned int mask_table[] = {
00045        0x00000000, 0x00000001, 0x00000003, 0x00000007,
00046        0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
00047        0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
00048        0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
00049        0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
00050        0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
00051        0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
00052        0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
00053        0xffffffff
00054 };
00055 
00056 
00057 /* color handling */
00058 
00059 typedef struct xlib_colormap_struct xlib_colormap;
00060 struct xlib_colormap_struct {
00061        int size;
00062        XColor *colors;
00063        Visual *visual;
00064        Colormap colormap;
00065 };
00066 
00067 
00068 /* from gdkvisual.c */
00069 static void
00070 visual_decompose_mask (unsigned long  mask,
00071                      int   *shift,
00072                      int   *prec)
00073 {
00074        *shift = 0;
00075        *prec = 0;
00076 
00077        while (!(mask & 0x1)) {
00078               (*shift)++;
00079               mask >>= 1;
00080        }
00081 
00082        while (mask & 0x1) {
00083               (*prec)++;
00084               mask >>= 1;
00085        }
00086 }
00087 
00088 static int x_error;
00089 
00090 static int
00091 handle_x_error (Display *dpy, XErrorEvent *ev)
00092 {
00093        x_error = 1;
00094        return 0;
00095 }
00096 
00097 static int
00098 drawable_is_pixmap (Drawable d)
00099 {
00100        /* copied from Imlib */
00101 
00102        XErrorHandler errh;
00103        XWindowAttributes wa;
00104        int is_pixmap;
00105 
00106        errh = XSetErrorHandler (handle_x_error);
00107        x_error = 0;
00108        XGetWindowAttributes (gdk_pixbuf_dpy, d, &wa);
00109        XSync (gdk_pixbuf_dpy, False);
00110        is_pixmap = x_error;
00111        XSetErrorHandler (errh);
00112 
00113        return is_pixmap;
00114 }
00115 
00116 
00117 
00118 /*
00119   convert 1 bits-pixel data
00120   no alpha
00121 */
00122 static void
00123 rgb1 (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00124 {
00125        int xx, yy;
00126        int width, height;
00127        int bpl;
00128        unsigned char *s;
00129        register unsigned char data;
00130        unsigned char *o;
00131        unsigned char *srow = image->data, *orow = pixels;
00132 
00133        d (printf ("1 bits/pixel\n"));
00134 
00135        /* convert upto 8 pixels/time */
00136        /* its probably not worth trying to make this run very fast, who uses
00137           1 bit displays anymore? */
00138        width = image->width;
00139        height = image->height;
00140        bpl = image->bytes_per_line;
00141 
00142        for (yy = 0; yy < height; yy++) {
00143               s = srow;
00144               o = orow;
00145 
00146               for (xx = 0; xx < width; xx ++) {
00147                      data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
00148                      *o++ = colormap->colors[data].red;
00149                      *o++ = colormap->colors[data].green;
00150                      *o++ = colormap->colors[data].blue;
00151               }
00152               srow += bpl;
00153               orow += rowstride;
00154        }
00155 }
00156 
00157 /*
00158   convert 1 bits/pixel data
00159   with alpha
00160 */
00161 static void
00162 rgb1a (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00163 {
00164        int xx, yy;
00165        int width, height;
00166        int bpl;
00167        unsigned char *s;
00168        register unsigned char data;
00169        unsigned char *o;
00170        unsigned char *srow = image->data, *orow = pixels;
00171        unsigned int remap[2];
00172 
00173        d (printf ("1 bits/pixel\n"));
00174 
00175        /* convert upto 8 pixels/time */
00176        /* its probably not worth trying to make this run very fast, who uses
00177           1 bit displays anymore? */
00178        width = image->width;
00179        height = image->height;
00180        bpl = image->bytes_per_line;
00181 
00182        for (xx = 0; xx < 2; xx++) {
00183 #ifdef LITTLE
00184               remap[xx] = 0xff000000
00185                      | colormap->colors[xx].blue << 16
00186                      | colormap->colors[xx].green << 8
00187                      | colormap->colors[xx].red;
00188 #else
00189               remap[xx] = 0xff
00190                      | colormap->colors[xx].red << 24
00191                      | colormap->colors[xx].green << 16
00192                      | colormap->colors[xx].blue << 8;
00193 #endif
00194        }
00195 
00196        for (yy = 0; yy < height; yy++) {
00197               s = srow;
00198               o = orow;
00199 
00200               for (xx = 0; xx < width; xx ++) {
00201                      data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
00202                      *o++ = remap[data];
00203               }
00204               srow += bpl;
00205               orow += rowstride;
00206        }
00207 }
00208 
00209 /*
00210   convert 8 bits/pixel data
00211   no alpha
00212 */
00213 static void
00214 rgb8 (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00215 {
00216        int xx, yy;
00217        int width, height;
00218        int bpl;
00219        unsigned int mask;
00220        register unsigned int data;
00221        unsigned char *srow = image->data, *orow = pixels;
00222        register unsigned char *s;
00223        register unsigned char *o;
00224 
00225        width = image->width;
00226        height = image->height;
00227        bpl = image->bytes_per_line;
00228 
00229        d (printf ("8 bit, no alpha output\n"));
00230 
00231        mask = mask_table[image->depth];
00232 
00233        for (yy = 0; yy < height; yy++) {
00234               s = srow;
00235               o = orow;
00236               for (xx = 0; xx < width; xx++) {
00237                      data = *s++ & mask;
00238                      *o++ = colormap->colors[data].red;
00239                      *o++ = colormap->colors[data].green;
00240                      *o++ = colormap->colors[data].blue;
00241               }
00242               srow += bpl;
00243               orow += rowstride;
00244        }
00245 }
00246 
00247 /*
00248   convert 8 bits/pixel data
00249   with alpha
00250 */
00251 static void
00252 rgb8a (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00253 {
00254        int xx, yy;
00255        int width, height;
00256        int bpl;
00257        unsigned int mask;
00258        register unsigned int data;
00259        unsigned int remap[256];
00260        register unsigned char *s;  /* read 2 pixels at once */
00261        register unsigned int *o;
00262        unsigned char *srow = image->data, *orow = pixels;
00263 
00264        width = image->width;
00265        height = image->height;
00266        bpl = image->bytes_per_line;
00267 
00268        d (printf ("8 bit, with alpha output\n"));
00269 
00270        mask = mask_table[image->depth];
00271 
00272        for (xx = 0; xx < colormap->size; xx++) {
00273 #ifdef LITTLE
00274               remap[xx] = 0xff000000
00275                      | colormap->colors[xx].blue << 16
00276                      | colormap->colors[xx].green << 8
00277                      | colormap->colors[xx].red;
00278 #else
00279               remap[xx] = 0xff
00280                      | colormap->colors[xx].red << 24
00281                      | colormap->colors[xx].green << 16
00282                      | colormap->colors[xx].blue << 8;
00283 #endif
00284        }
00285 
00286        for (yy = 0; yy < height; yy++) {
00287               s = srow;
00288               o = (unsigned int *) orow;
00289               for (xx = 0; xx < width; xx ++) {
00290                      data = *s++ & mask;
00291                      *o++ = remap[data];
00292               }
00293               srow += bpl;
00294               orow += rowstride;
00295        }
00296 }
00297 
00298 /*
00299   convert 16 bits/pixel data
00300   no alpha
00301   data in lsb format
00302 */
00303 static void
00304 rgb565lsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00305 {
00306        int xx, yy;
00307        int width, height;
00308        int bpl;
00309 
00310 #ifdef LITTLE
00311        register unsigned int *s;   /* read 2 pixels at once */
00312 #else
00313        register unsigned char *s;  /* read 2 pixels at once */
00314 #endif
00315        register unsigned short *o;
00316        unsigned char *srow = image->data, *orow = pixels;
00317 
00318        width = image->width;
00319        height = image->height;
00320        bpl = image->bytes_per_line;
00321 
00322        for (yy = 0; yy < height; yy++) {
00323 #ifdef LITTLE
00324               s = (unsigned int *) srow;
00325 #else
00326               s = srow;
00327 #endif
00328               o = (unsigned short *) orow;
00329               for (xx = 1; xx < width; xx += 2) {
00330                      register unsigned int data;
00331 #ifdef LITTLE
00332                      data = *s++;
00333                      *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
00334                             | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
00335                      *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
00336                             | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
00337                      *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
00338                             | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
00339 #else
00340                      /* swap endianness first */
00341                      data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
00342                      s += 4;
00343                      *o++ = (data & 0xf800) | (data & 0xe000) >> 5
00344                             | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
00345                      *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
00346                             | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
00347                      *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
00348                             | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
00349 #endif
00350               }
00351               /* check for last remaining pixel */
00352               if (width & 1) {
00353                      register unsigned short data;
00354 #ifdef LITTLE
00355                      data = *((short *) s);
00356 #else
00357                      data = *((short *) s);
00358                      data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
00359 #endif
00360                      ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
00361                      ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
00362                      ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
00363               }
00364               srow += bpl;
00365               orow += rowstride;
00366        }
00367 }
00368 
00369 /*
00370   convert 16 bits/pixel data
00371   no alpha
00372   data in msb format
00373 */
00374 static void
00375 rgb565msb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00376 {
00377        int xx, yy;
00378        int width, height;
00379        int bpl;
00380 
00381 #ifdef LITTLE
00382        register unsigned char *s;  /* need to swap data order */
00383 #else
00384        register unsigned int *s;   /* read 2 pixels at once */
00385 #endif
00386        register unsigned short *o;
00387        unsigned char *srow = image->data, *orow = pixels;
00388 
00389        width = image->width;
00390        height = image->height;
00391        bpl = image->bytes_per_line;
00392 
00393        for (yy = 0; yy < height; yy++) {
00394 #ifdef LITTLE
00395               s = srow;
00396 #else
00397               s = (unsigned int *) srow;
00398 #endif
00399               o = (unsigned short *) orow;
00400               for (xx = 1; xx < width; xx += 2) {
00401                      register unsigned int data;
00402 #ifdef LITTLE
00403                      /* swap endianness first */
00404                      data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
00405                      s += 4;
00406                      *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
00407                             | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
00408                      *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
00409                             | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
00410                      *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
00411                             | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
00412 #else
00413                      data = *s++;
00414                      *o++ = (data & 0xf800) | (data & 0xe000) >> 5
00415                             | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
00416                      *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
00417                             | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
00418                      *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
00419                             | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
00420 #endif
00421               }
00422               /* check for last remaining pixel */
00423               if (width & 1) {
00424                      register unsigned short data;
00425 #ifdef LITTLE
00426                      data = *((short *) s);
00427                      data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
00428 #else
00429                      data = *((short *) s);
00430 #endif
00431                      ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
00432                      ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
00433                      ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
00434               }
00435               srow += bpl;
00436               orow += rowstride;
00437        }
00438 }
00439 
00440 /*
00441   convert 16 bits/pixel data
00442   with alpha
00443   data in lsb format
00444 */
00445 static void
00446 rgb565alsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00447 {
00448        int xx, yy;
00449        int width, height;
00450        int bpl;
00451 
00452 #ifdef LITTLE
00453        register unsigned short *s; /* read 1 pixels at once */
00454 #else
00455        register unsigned char *s;
00456 #endif
00457        register unsigned int *o;
00458 
00459        unsigned char *srow = image->data, *orow = pixels;
00460 
00461        width = image->width;
00462        height = image->height;
00463        bpl = image->bytes_per_line;
00464 
00465        for (yy = 0; yy < height; yy++) {
00466 #ifdef LITTLE
00467               s = (unsigned short *) srow;
00468 #else
00469               s = (unsigned char *) srow;
00470 #endif
00471               o = (unsigned int *) orow;
00472               for (xx = 0; xx < width; xx ++) {
00473                      register unsigned int data;
00474                      /*  rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */
00475                      /*  little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */
00476 #ifdef LITTLE
00477                      data = *s++;
00478                      *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
00479                             | (data & 0x7e0) << 5 | (data & 0x600) >> 1
00480                             | (data & 0x1f) << 19 | (data & 0x1c) << 14
00481                             | 0xff000000;
00482 #else
00483                      /* swap endianness first */
00484                      data = s[0] | s[1] << 8;
00485                      s += 2;
00486                      *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
00487                             | (data & 0x7e0) << 13 | (data & 0x600) << 7
00488                             | (data & 0x1f) << 11 | (data & 0x1c) << 6
00489                             | 0xff;
00490 #endif
00491               }
00492               srow += bpl;
00493               orow += rowstride;
00494        }
00495 }
00496 
00497 /*
00498   convert 16 bits/pixel data
00499   with alpha
00500   data in msb format
00501 */
00502 static void
00503 rgb565amsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00504 {
00505        int xx, yy;
00506        int width, height;
00507        int bpl;
00508 
00509 #ifdef LITTLE
00510        register unsigned char *s;
00511 #else
00512        register unsigned short *s; /* read 1 pixels at once */
00513 #endif
00514        register unsigned int *o;
00515 
00516        unsigned char *srow = image->data, *orow = pixels;
00517 
00518        width = image->width;
00519        height = image->height;
00520        bpl = image->bytes_per_line;
00521 
00522        for (yy = 0; yy < height; yy++) {
00523               s = srow;
00524               o = (unsigned int *) orow;
00525               for (xx = 0; xx < width; xx ++) {
00526                      register unsigned int data;
00527                      /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */
00528                      /*  little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */
00529 #ifdef LITTLE
00530                      /* swap endianness first */
00531                      data = s[0] | s[1] << 8;
00532                      s += 2;
00533                      *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
00534                             | (data & 0x7e0) << 5 | (data & 0x600) >> 1
00535                             | (data & 0x1f) << 19 | (data & 0x1c) << 14
00536                             | 0xff000000;
00537 #else
00538                      data = *s++;
00539                      *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
00540                             | (data & 0x7e0) << 13 | (data & 0x600) << 7
00541                             | (data & 0x1f) << 11 | (data & 0x1c) << 6
00542                             | 0xff;
00543 #endif
00544               }
00545               srow += bpl;
00546               orow += rowstride;
00547        }
00548 }
00549 
00550 /*
00551   convert 15 bits/pixel data
00552   no alpha
00553   data in lsb format
00554 */
00555 static void
00556 rgb555lsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00557 {
00558        int xx, yy;
00559        int width, height;
00560        int bpl;
00561 
00562 #ifdef LITTLE
00563        register unsigned int *s;   /* read 2 pixels at once */
00564 #else
00565        register unsigned char *s;  /* read 2 pixels at once */
00566 #endif
00567        register unsigned short *o;
00568        unsigned char *srow = image->data, *orow = pixels;
00569 
00570        width = image->width;
00571        height = image->height;
00572        bpl = image->bytes_per_line;
00573 
00574        for (yy = 0; yy < height; yy++) {
00575 #ifdef LITTLE
00576               s = (unsigned int *) srow;
00577 #else
00578               s = srow;
00579 #endif
00580               o = (unsigned short *) orow;
00581               for (xx = 1; xx < width; xx += 2) {
00582                      register unsigned int data;
00583 #ifdef LITTLE
00584                      data = *s++;
00585                      *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
00586                             | (data & 0x3e0) << 6 | (data & 0x380) << 1;
00587                      *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
00588                             | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
00589                      *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
00590                             | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
00591 #else
00592                      /* swap endianness first */
00593                      data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
00594                      s += 4;
00595                      *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
00596                             | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
00597                      *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
00598                             | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
00599                      *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
00600                             | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
00601 #endif
00602               }
00603               /* check for last remaining pixel */
00604               if (width & 1) {
00605                      register unsigned short data;
00606 #ifdef LITTLE
00607                      data = *((short *) s);
00608 #else
00609                      data = *((short *) s);
00610                      data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
00611 #endif
00612                      ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
00613                      ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
00614                      ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
00615               }
00616               srow += bpl;
00617               orow += rowstride;
00618        }
00619 }
00620 
00621 /*
00622   convert 15 bits/pixel data
00623   no alpha
00624   data in msb format
00625 */
00626 static void
00627 rgb555msb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00628 {
00629        int xx, yy;
00630        int width, height;
00631        int bpl;
00632 
00633 #ifdef LITTLE
00634        register unsigned char *s;  /* read 2 pixels at once */
00635 #else
00636        register unsigned int *s;   /* read 2 pixels at once */
00637 #endif
00638        register unsigned short *o;
00639        unsigned char *srow = image->data, *orow = pixels;
00640 
00641        width = image->width;
00642        height = image->height;
00643        bpl = image->bytes_per_line;
00644 
00645        for (yy = 0; yy < height; yy++) {
00646               s = srow;
00647               o = (unsigned short *) orow;
00648               for (xx = 1; xx < width; xx += 2) {
00649                      register unsigned int data;
00650 #ifdef LITTLE
00651                      /* swap endianness first */
00652                      data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
00653                      s += 4;
00654                      *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
00655                             | (data & 0x3e0) << 6 | (data & 0x380) << 1;
00656                      *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
00657                             | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
00658                      *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
00659                             | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
00660 #else
00661                      data = *s++;
00662                      *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
00663                             | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
00664                      *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
00665                             | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
00666                      *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
00667                             | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
00668 #endif
00669               }
00670               /* check for last remaining pixel */
00671               if (width & 1) {
00672                      register unsigned short data;
00673 #ifdef LITTLE
00674                      data = *((short *) s);
00675                      data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
00676 #else
00677                      data = *((short *) s);
00678 #endif
00679                      ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
00680                      ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
00681                      ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
00682               }
00683               srow += bpl;
00684               orow += rowstride;
00685        }
00686 }
00687 
00688 /*
00689   convert 15 bits/pixel data
00690   with alpha
00691   data in lsb format
00692 */
00693 static void
00694 rgb555alsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00695 {
00696        int xx, yy;
00697        int width, height;
00698        int bpl;
00699 
00700 #ifdef LITTLE
00701        register unsigned short *s; /* read 1 pixels at once */
00702 #else
00703        register unsigned char *s;
00704 #endif
00705        register unsigned int *o;
00706 
00707        unsigned char *srow = image->data, *orow = pixels;
00708 
00709        width = image->width;
00710        height = image->height;
00711        bpl = image->bytes_per_line;
00712 
00713        for (yy = 0; yy < height; yy++) {
00714 #ifdef LITTLE
00715               s = (unsigned short *) srow;
00716 #else
00717               s = srow;
00718 #endif
00719               o = (unsigned int *) orow;
00720               for (xx = 0; xx < width; xx++) {
00721                      register unsigned int data;
00722                      /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
00723                      /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
00724 #ifdef LITTLE
00725                      data = *s++;
00726                      *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
00727                             | (data & 0x3e0) << 6 | (data & 0x380) << 1
00728                             | (data & 0x1f) << 19 | (data & 0x1c) << 14
00729                             | 0xff000000;
00730 #else
00731                      /* swap endianness first */
00732                      data = s[0] | s[1] << 8;
00733                      s += 2;
00734                      *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
00735                             | (data & 0x3e0) << 14 | (data & 0x380) << 9
00736                             | (data & 0x1f) << 11 | (data & 0x1c) << 6
00737                             | 0xff;
00738 #endif
00739               }
00740               srow += bpl;
00741               orow += rowstride;
00742        }
00743 }
00744 
00745 /*
00746   convert 15 bits/pixel data
00747   with alpha
00748   data in msb format
00749 */
00750 static void
00751 rgb555amsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00752 {
00753        int xx, yy;
00754        int width, height;
00755        int bpl;
00756 
00757 #ifdef LITTLE
00758        register unsigned short *s; /* read 1 pixels at once */
00759 #else
00760        register unsigned char *s;
00761 #endif
00762        register unsigned int *o;
00763 
00764        unsigned char *srow = image->data, *orow = pixels;
00765 
00766        width = image->width;
00767        height = image->height;
00768        bpl = image->bytes_per_line;
00769 
00770        for (yy = 0; yy < height; yy++) {
00771 #ifdef LITTLE
00772               s = (unsigned short *) srow;
00773 #else
00774               s = srow;
00775 #endif
00776               o = (unsigned int *) orow;
00777               for (xx = 0; xx < width; xx++) {
00778                      register unsigned int data;
00779                      /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
00780                      /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
00781 #ifdef LITTLE
00782                      /* swap endianness first */
00783                      data = s[0] | s[1] << 8;
00784                      s += 2;
00785                      *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
00786                             | (data & 0x3e0) << 6 | (data & 0x380) << 1
00787                             | (data & 0x1f) << 19 | (data & 0x1c) << 14
00788                             | 0xff000000;
00789 #else
00790                      data = *s++;
00791                      *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
00792                             | (data & 0x3e0) << 14 | (data & 0x380) << 9
00793                             | (data & 0x1f) << 11 | (data & 0x1c) << 6
00794                             | 0xff;
00795 #endif
00796               }
00797               srow += bpl;
00798               orow += rowstride;
00799        }
00800 }
00801 
00802 
00803 static void
00804 rgb888alsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00805 {
00806        int xx, yy;
00807        int width, height;
00808        int bpl;
00809 
00810        unsigned char *s;    /* for byte order swapping */
00811        unsigned char *o;
00812        unsigned char *srow = image->data, *orow = pixels;
00813 
00814        width = image->width;
00815        height = image->height;
00816        bpl = image->bytes_per_line;
00817 
00818        d (printf ("32 bits/pixel with alpha\n"));
00819 
00820        /* lsb data */
00821        for (yy = 0; yy < height; yy++) {
00822               s = srow;
00823               o = orow;
00824               for (xx = 0; xx < width; xx++) {
00825                      *o++ = s[2];
00826                      *o++ = s[1];
00827                      *o++ = s[0];
00828                      *o++ = 0xff;
00829                      s += 4;
00830               }
00831               srow += bpl;
00832               orow += rowstride;
00833        }
00834 }
00835 
00836 static void
00837 rgb888lsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00838 {
00839        int xx, yy;
00840        int width, height;
00841        int bpl;
00842 
00843        unsigned char *srow = image->data, *orow = pixels;
00844        unsigned char *o, *s;
00845 
00846        width = image->width;
00847        height = image->height;
00848        bpl = image->bytes_per_line;
00849 
00850        d (printf ("32 bit, lsb, no alpha\n"));
00851 
00852        for (yy = 0; yy < height; yy++) {
00853               s = srow;
00854               o = orow;
00855               for (xx = 0; xx < width; xx++) {
00856                      *o++ = s[2];
00857                      *o++ = s[1];
00858                      *o++ = s[0];
00859                      s += 4;
00860               }
00861               srow += bpl;
00862               orow += rowstride;
00863        }
00864 }
00865 
00866 static void
00867 rgb888amsb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00868 {
00869        int xx, yy;
00870        int width, height;
00871        int bpl;
00872 
00873        unsigned char *srow = image->data, *orow = pixels;
00874 #ifdef LITTLE
00875        unsigned int *o;
00876        unsigned int *s;
00877 #else
00878        unsigned char *s;    /* for byte order swapping */
00879        unsigned char *o;
00880 #endif
00881 
00882        d (printf ("32 bit, msb, with alpha\n"));
00883 
00884        width = image->width;
00885        height = image->height;
00886        bpl = image->bytes_per_line;
00887 
00888        /* msb data */
00889        for (yy = 0; yy < height; yy++) {
00890 #ifdef LITTLE
00891               s = (unsigned int *) srow;
00892               o = (unsigned int *) orow;
00893 #else
00894               s = srow;
00895               o = orow;
00896 #endif
00897               for (xx = 0; xx < width; xx++) {
00898 #ifdef LITTLE
00899                      *o++ = s[1];
00900                      *o++ = s[2];
00901                      *o++ = s[3];
00902                      *o++ = 0xff;
00903                      s += 4;
00904 #else
00905                      *o++ = (*s << 8) | 0xff; /* untested */
00906                      s++;
00907 #endif
00908               }
00909               srow += bpl;
00910               orow += rowstride;
00911        }
00912 }
00913 
00914 static void
00915 rgb888msb (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
00916 {
00917        int xx, yy;
00918        int width, height;
00919        int bpl;
00920 
00921        unsigned char *srow = image->data, *orow = pixels;
00922        unsigned char *s;
00923        unsigned char *o;
00924 
00925        d (printf ("32 bit, msb, no alpha\n"));
00926 
00927        width = image->width;
00928        height = image->height;
00929        bpl = image->bytes_per_line;
00930 
00931        for (yy = 0; yy < height; yy++) {
00932               s = srow;
00933               o = orow;
00934               for (xx = 0; xx < width; xx++) {
00935                      *o++ = s[1];
00936                      *o++ = s[2];
00937                      *o++ = s[3];
00938                      s += 4;
00939               }
00940               srow += bpl;
00941               orow += rowstride;
00942        }
00943 }
00944 
00945 /*
00946   This should work correctly with any display/any endianness, but will probably
00947   run quite slow
00948 */
00949 static void
00950 convert_real_slow (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *cmap, int alpha)
00951 {
00952        int xx, yy;
00953        int width, height;
00954        int bpl;
00955        unsigned char *srow = image->data, *orow = pixels;
00956        unsigned char *s;
00957        unsigned char *o;
00958        unsigned int pixel;
00959        Visual *v;
00960        unsigned char component;
00961        int i;
00962        int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec;
00963 
00964        width = image->width;
00965        height = image->height;
00966        bpl = image->bytes_per_line;
00967        v = cmap->visual;
00968 
00969        visual_decompose_mask (v->red_mask, &red_shift, &red_prec);
00970        visual_decompose_mask (v->green_mask, &green_shift, &green_prec);
00971        visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec);
00972 
00973        d(printf("rgb  mask/shift/prec = %x:%x:%x %d:%d:%d  %d:%d:%d\n",
00974                v->red_mask, v->green_mask, v->blue_mask,
00975                red_shift, green_shift, blue_shift,
00976                red_prec, green_prec, blue_prec));
00977 
00978        for (yy = 0; yy < height; yy++) {
00979               s = srow;
00980               o = orow;
00981               for (xx = 0; xx < width; xx++) {
00982                      pixel = XGetPixel (image, xx, yy);
00983                      switch (v->class) {
00984                             /* I assume this is right for static & greyscale's too? */
00985                      case StaticGray:
00986                      case GrayScale:
00987                      case StaticColor:
00988                      case PseudoColor:
00989                             *o++ = cmap->colors[pixel].red;
00990                             *o++ = cmap->colors[pixel].green;
00991                             *o++ = cmap->colors[pixel].blue;
00992                             break;
00993                      case TrueColor:
00994                             /* This is odd because it must sometimes shift left (otherwise
00995                                I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic
00996                                should work for all bit sizes/shifts/etc. */
00997                             component = 0;
00998                             for (i = 24; i < 32; i += red_prec)
00999                                    component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i;
01000                             *o++ = component;
01001                             component = 0;
01002                             for (i = 24; i < 32; i += green_prec)
01003                                    component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i;
01004                             *o++ = component;
01005                             component = 0;
01006                             for (i = 24; i < 32; i += blue_prec)
01007                                    component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i;
01008                             *o++ = component;
01009                             break;
01010                      case DirectColor:
01011                             *o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red;
01012                             *o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green;
01013                             *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue;
01014                             break;
01015                      }
01016                      if (alpha)
01017                             *o++ = 0xff;
01018               }
01019               srow += bpl;
01020               orow += rowstride;
01021        }
01022 }
01023 
01024 typedef void (* cfunc) (XImage *image, unsigned char *pixels, int rowstride, xlib_colormap *cmap);
01025 
01026 static cfunc convert_map[] = {
01027        rgb1,rgb1,rgb1a,rgb1a,
01028        rgb8,rgb8,rgb8a,rgb8a,
01029        rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
01030        rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
01031        rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
01032 };
01033 
01034 /*
01035   perform actual conversion
01036 
01037   If we can, try and use the optimised code versions, but as a default
01038   fallback, and always for direct colour, use the generic/slow but complete
01039   conversion function.
01040 */
01041 static void
01042 rgbconvert (XImage *image, unsigned char *pixels, int rowstride, int alpha, xlib_colormap *cmap)
01043 {
01044        int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
01045        int bank=5;          /* default fallback converter */
01046        Visual *v = cmap->visual;
01047 
01048        d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
01049        d(printf("image depth = %d, bpp = %d\n", image->depth, image->bits_per_pixel));
01050 
01051        switch (v->class) {
01052                             /* I assume this is right for static & greyscale's too? */
01053        case StaticGray:
01054        case GrayScale:
01055        case StaticColor:
01056        case PseudoColor:
01057               switch (image->bits_per_pixel) {
01058               case 1:
01059                      bank = 0;
01060                      break;
01061               case 8:
01062                      bank = 1;
01063                      break;
01064               }
01065               break;
01066        case TrueColor:
01067               switch (image->depth) {
01068               case 15:
01069                      if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
01070                          && image->bits_per_pixel == 16)
01071                             bank = 2;
01072                      break;
01073               case 16:
01074                      if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
01075                          && image->bits_per_pixel == 16)
01076                             bank = 3;
01077                      break;
01078               case 24:
01079               case 32:
01080                      if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
01081                          && image->bits_per_pixel == 32)
01082                             bank = 4;
01083                      break;
01084               }
01085               break;
01086        case DirectColor:
01087               /* always use the slow version */
01088               break;
01089        }
01090 
01091        d(printf("converting using conversion function in bank %d\n", bank));
01092 
01093        if (bank==5) {
01094               convert_real_slow(image, pixels, rowstride, cmap, alpha);
01095        } else {
01096               index |= bank << 2;
01097               (* convert_map[index]) (image, pixels, rowstride, cmap);
01098        }
01099 }
01100 
01101 static int
01102 xlib_window_is_viewable (Window w)
01103 {
01104        XWindowAttributes wa;
01105 
01106        while (w != 0) {
01107               Window parent, root, *children;
01108               int nchildren;
01109 
01110               XGetWindowAttributes (gdk_pixbuf_dpy, w, &wa);
01111               if (wa.map_state != IsViewable)
01112                      return 0;
01113 
01114               if (!XQueryTree (gdk_pixbuf_dpy, w, &root,
01115                              &parent, &children, &nchildren))
01116                      return 0;
01117 
01118               if (nchildren > 0)
01119                      XFree (children);
01120 
01121               if (parent == root)
01122                      return 1;
01123 
01124               w = parent;
01125        }
01126 
01127        return 0;
01128 }
01129 
01130 static int
01131 xlib_window_get_origin (Window w, int *x, int *y)
01132 {
01133        Window child;
01134        return XTranslateCoordinates (gdk_pixbuf_dpy, w,
01135                                   RootWindow (gdk_pixbuf_dpy,
01136                                             gdk_pixbuf_screen),
01137                                   0, 0, x, y, &child);
01138 }