~ubuntu-branches/ubuntu/precise/gdk-pixbuf/precise-proposed

« back to all changes in this revision

Viewing changes to contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-drawable.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-07-23 11:26:25 UTC
  • mto: (4.1.1 sid) (33.1.2 sid) (1.2.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20100723112625-1ybus2sr4hyhmlku
Tags: upstream-2.21.6
ImportĀ upstreamĀ versionĀ 2.21.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/* GdkPixbuf library - convert X drawable information to RGB
 
3
 *
 
4
 * Copyright (C) 1999 Michael Zucchi
 
5
 *
 
6
 * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
 
7
 *          Cody Russell <bratsche@dfw.net>
 
8
 *          Federico Mena-Quintero <federico@gimp.org>
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Library General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2 of the License, or (at your option) any later version.
 
14
 *
 
15
 * This library is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * Library General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Library General Public
 
21
 * License along with this library; if not, write to the
 
22
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
23
 * Boston, MA 02111-1307, USA.
 
24
 */
 
25
 
 
26
/* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */
 
27
 
 
28
 
 
29
#include "config.h"
 
30
#include <stdio.h>
 
31
#include <string.h>
 
32
#include "gdk-pixbuf-xlib-private.h"
 
33
#include <X11/Xlib.h>
 
34
#include <X11/Xutil.h>
 
35
 
 
36
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
 
37
#define LITTLE
 
38
#endif
 
39
#define d(x)
 
40
 
 
41
 
 
42
 
 
43
static const guint32 mask_table[] = {
 
44
        0x00000000, 0x00000001, 0x00000003, 0x00000007,
 
45
        0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
 
46
        0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
 
47
        0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
 
48
        0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
 
49
        0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
 
50
        0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
 
51
        0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
 
52
        0xffffffff
 
53
};
 
54
 
 
55
 
 
56
/* color handling */
 
57
 
 
58
typedef struct xlib_colormap_struct xlib_colormap;
 
59
struct xlib_colormap_struct {
 
60
        int size;
 
61
        XColor *colors;
 
62
        Visual *visual;
 
63
        Colormap colormap;
 
64
};
 
65
 
 
66
static xlib_colormap *
 
67
xlib_get_colormap (Colormap id, Visual *visual)
 
68
{
 
69
        int i;
 
70
        xlib_colormap *xc = g_new (xlib_colormap, 1);
 
71
 
 
72
        xc->size = visual->map_entries;
 
73
        xc->colors = g_new (XColor, xc->size);
 
74
        xc->visual = visual;
 
75
        xc->colormap = id;
 
76
 
 
77
        for (i = 0; i < xc->size; i++) {
 
78
                xc->colors[i].pixel = i;
 
79
                xc->colors[i].flags = DoRed | DoGreen | DoBlue;
 
80
        }
 
81
 
 
82
        XQueryColors (gdk_pixbuf_dpy, xc->colormap, xc->colors, xc->size);
 
83
 
 
84
        return xc;
 
85
}
 
86
 
 
87
static void
 
88
xlib_colormap_free (xlib_colormap *xc)
 
89
{
 
90
        g_free (xc->colors);
 
91
        g_free (xc);
 
92
}
 
93
 
 
94
/* from gdkvisual.c */
 
95
static void
 
96
visual_decompose_mask (gulong  mask,
 
97
                       gint   *shift,
 
98
                       gint   *prec)
 
99
{
 
100
        *shift = 0;
 
101
        *prec = 0;
 
102
 
 
103
        while (!(mask & 0x1)) {
 
104
                (*shift)++;
 
105
                mask >>= 1;
 
106
        }
 
107
 
 
108
        while (mask & 0x1) {
 
109
                (*prec)++;
 
110
                mask >>= 1;
 
111
        }
 
112
}
 
113
 
 
114
static gboolean x_error;
 
115
 
 
116
static int
 
117
handle_x_error (Display *dpy, XErrorEvent *ev)
 
118
{
 
119
        x_error = TRUE;
 
120
        return 0;
 
121
}
 
122
 
 
123
static gboolean
 
124
drawable_is_pixmap (Drawable d)
 
125
{
 
126
        /* copied from Imlib */
 
127
 
 
128
        XErrorHandler errh;
 
129
        XWindowAttributes wa;
 
130
        gboolean is_pixmap;
 
131
 
 
132
        errh = XSetErrorHandler (handle_x_error);
 
133
        x_error = FALSE;
 
134
        XGetWindowAttributes (gdk_pixbuf_dpy, d, &wa);
 
135
        XSync (gdk_pixbuf_dpy, False);
 
136
        is_pixmap = x_error;
 
137
        XSetErrorHandler (errh);
 
138
 
 
139
        return is_pixmap;
 
140
}
 
141
 
 
142
 
 
143
 
 
144
/*
 
145
  convert 1 bits-pixel data
 
146
  no alpha
 
147
*/
 
148
static void
 
149
rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
150
{
 
151
        int xx, yy;
 
152
        int width, height;
 
153
        int bpl;
 
154
        register guint8 data;
 
155
        guint8 *o;
 
156
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
157
 
 
158
        d (printf ("1 bits/pixel\n"));
 
159
 
 
160
        /* convert upto 8 pixels/time */
 
161
        /* its probably not worth trying to make this run very fast, who uses
 
162
           1 bit displays anymore? */
 
163
        width = image->width;
 
164
        height = image->height;
 
165
        bpl = image->bytes_per_line;
 
166
 
 
167
        for (yy = 0; yy < height; yy++) {
 
168
                o = orow;
 
169
 
 
170
                for (xx = 0; xx < width; xx ++) {
 
171
                        data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
 
172
                        *o++ = colormap->colors[data].red;
 
173
                        *o++ = colormap->colors[data].green;
 
174
                        *o++ = colormap->colors[data].blue;
 
175
                }
 
176
                srow += bpl;
 
177
                orow += rowstride;
 
178
        }
 
179
}
 
180
 
 
181
/*
 
182
  convert 1 bits/pixel data
 
183
  with alpha
 
184
*/
 
185
static void
 
186
rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
187
{
 
188
        int xx, yy;
 
189
        int width, height;
 
190
        int bpl;
 
191
        register guint8 data;
 
192
        guint8 *o;
 
193
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
194
        guint32 remap[2];
 
195
 
 
196
        d (printf ("1 bits/pixel\n"));
 
197
 
 
198
        /* convert upto 8 pixels/time */
 
199
        /* its probably not worth trying to make this run very fast, who uses
 
200
           1 bit displays anymore? */
 
201
        width = image->width;
 
202
        height = image->height;
 
203
        bpl = image->bytes_per_line;
 
204
 
 
205
        for (xx = 0; xx < 2; xx++) {
 
206
#ifdef LITTLE
 
207
                remap[xx] = 0xff000000
 
208
                        | colormap->colors[xx].blue << 16
 
209
                        | colormap->colors[xx].green << 8
 
210
                        | colormap->colors[xx].red;
 
211
#else
 
212
                remap[xx] = 0xff
 
213
                        | colormap->colors[xx].red << 24
 
214
                        | colormap->colors[xx].green << 16
 
215
                        | colormap->colors[xx].blue << 8;
 
216
#endif
 
217
        }
 
218
 
 
219
        for (yy = 0; yy < height; yy++) {
 
220
                o = orow;
 
221
 
 
222
                for (xx = 0; xx < width; xx ++) {
 
223
                        data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
 
224
                        *o++ = remap[data];
 
225
                }
 
226
                srow += bpl;
 
227
                orow += rowstride;
 
228
        }
 
229
}
 
230
 
 
231
/*
 
232
  convert 8 bits/pixel data
 
233
  no alpha
 
234
*/
 
235
static void
 
236
rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
237
{
 
238
        int xx, yy;
 
239
        int width, height;
 
240
        int bpl;
 
241
        guint32 mask;
 
242
        register guint32 data;
 
243
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
244
        register guint8 *s;
 
245
        register guint8 *o;
 
246
 
 
247
        width = image->width;
 
248
        height = image->height;
 
249
        bpl = image->bytes_per_line;
 
250
 
 
251
        d (printf ("8 bit, no alpha output\n"));
 
252
 
 
253
        mask = mask_table[image->depth];
 
254
 
 
255
        for (yy = 0; yy < height; yy++) {
 
256
                s = srow;
 
257
                o = orow;
 
258
                for (xx = 0; xx < width; xx++) {
 
259
                        data = *s++ & mask;
 
260
                        *o++ = colormap->colors[data].red;
 
261
                        *o++ = colormap->colors[data].green;
 
262
                        *o++ = colormap->colors[data].blue;
 
263
                }
 
264
                srow += bpl;
 
265
                orow += rowstride;
 
266
        }
 
267
}
 
268
 
 
269
/*
 
270
  convert 8 bits/pixel data
 
271
  with alpha
 
272
*/
 
273
static void
 
274
rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
275
{
 
276
        int xx, yy;
 
277
        int width, height;
 
278
        int bpl;
 
279
        guint32 mask;
 
280
        register guint32 data;
 
281
        guint32 remap[256];
 
282
        register guint8 *s;     /* read 2 pixels at once */
 
283
        register guint32 *o;
 
284
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
285
 
 
286
        width = image->width;
 
287
        height = image->height;
 
288
        bpl = image->bytes_per_line;
 
289
 
 
290
        d (printf ("8 bit, with alpha output\n"));
 
291
 
 
292
        mask = mask_table[image->depth];
 
293
 
 
294
        for (xx = 0; xx < colormap->size; xx++) {
 
295
#ifdef LITTLE
 
296
                remap[xx] = 0xff000000
 
297
                        | colormap->colors[xx].blue << 16
 
298
                        | colormap->colors[xx].green << 8
 
299
                        | colormap->colors[xx].red;
 
300
#else
 
301
                remap[xx] = 0xff
 
302
                        | colormap->colors[xx].red << 24
 
303
                        | colormap->colors[xx].green << 16
 
304
                        | colormap->colors[xx].blue << 8;
 
305
#endif
 
306
        }
 
307
 
 
308
        for (yy = 0; yy < height; yy++) {
 
309
                s = srow;
 
310
                o = (guint32 *) orow;
 
311
                for (xx = 0; xx < width; xx ++) {
 
312
                        data = *s++ & mask;
 
313
                        *o++ = remap[data];
 
314
                }
 
315
                srow += bpl;
 
316
                orow += rowstride;
 
317
        }
 
318
}
 
319
 
 
320
/*
 
321
  convert 16 bits/pixel data
 
322
  no alpha
 
323
  data in lsb format
 
324
*/
 
325
static void
 
326
rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
327
{
 
328
        int xx, yy;
 
329
        int width, height;
 
330
        int bpl;
 
331
 
 
332
#ifdef LITTLE
 
333
        register guint32 *s;    /* read 2 pixels at once */
 
334
#else
 
335
        register guint8 *s;     /* read 2 pixels at once */
 
336
#endif
 
337
        register guint16 *o;
 
338
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
339
 
 
340
        width = image->width;
 
341
        height = image->height;
 
342
        bpl = image->bytes_per_line;
 
343
 
 
344
        for (yy = 0; yy < height; yy++) {
 
345
#ifdef LITTLE
 
346
                s = (guint32 *) srow;
 
347
#else
 
348
                s = srow;
 
349
#endif
 
350
                o = (guint16 *) orow;
 
351
                for (xx = 1; xx < width; xx += 2) {
 
352
                        register guint32 data;
 
353
#ifdef LITTLE
 
354
                        data = *s++;
 
355
                        *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
 
356
                                | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
 
357
                        *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
 
358
                                | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
 
359
                        *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
 
360
                                | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
 
361
#else
 
362
                        /* swap endianness first */
 
363
                        data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
 
364
                        s += 4;
 
365
                        *o++ = (data & 0xf800) | (data & 0xe000) >> 5
 
366
                                | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
 
367
                        *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
 
368
                                | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
 
369
                        *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
 
370
                                | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
 
371
#endif
 
372
                }
 
373
                /* check for last remaining pixel */
 
374
                if (width & 1) {
 
375
                        register guint16 data;
 
376
#ifdef LITTLE
 
377
                        data = *((short *) s);
 
378
#else
 
379
                        data = *((short *) s);
 
380
                        data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
 
381
#endif
 
382
                        ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
 
383
                        ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
 
384
                        ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
 
385
                }
 
386
                srow += bpl;
 
387
                orow += rowstride;
 
388
        }
 
389
}
 
390
 
 
391
/*
 
392
  convert 16 bits/pixel data
 
393
  no alpha
 
394
  data in msb format
 
395
*/
 
396
static void
 
397
rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
398
{
 
399
        int xx, yy;
 
400
        int width, height;
 
401
        int bpl;
 
402
 
 
403
#ifdef LITTLE
 
404
        register guint8 *s;     /* need to swap data order */
 
405
#else
 
406
        register guint32 *s;    /* read 2 pixels at once */
 
407
#endif
 
408
        register guint16 *o;
 
409
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
410
 
 
411
        width = image->width;
 
412
        height = image->height;
 
413
        bpl = image->bytes_per_line;
 
414
 
 
415
        for (yy = 0; yy < height; yy++) {
 
416
#ifdef LITTLE
 
417
                s = srow;
 
418
#else
 
419
                s = (guint32 *) srow;
 
420
#endif
 
421
                o = (guint16 *) orow;
 
422
                for (xx = 1; xx < width; xx += 2) {
 
423
                        register guint32 data;
 
424
#ifdef LITTLE
 
425
                        /* swap endianness first */
 
426
                        data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
 
427
                        s += 4;
 
428
                        *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
 
429
                                | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
 
430
                        *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
 
431
                                | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
 
432
                        *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
 
433
                                | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
 
434
#else
 
435
                        data = *s++;
 
436
                        *o++ = (data & 0xf800) | (data & 0xe000) >> 5
 
437
                                | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
 
438
                        *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
 
439
                                | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
 
440
                        *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
 
441
                                | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
 
442
#endif
 
443
                }
 
444
                /* check for last remaining pixel */
 
445
                if (width & 1) {
 
446
                        register guint16 data;
 
447
#ifdef LITTLE
 
448
                        data = *((short *) s);
 
449
                        data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
 
450
#else
 
451
                        data = *((short *) s);
 
452
#endif
 
453
                        ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
 
454
                        ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
 
455
                        ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
 
456
                }
 
457
                srow += bpl;
 
458
                orow += rowstride;
 
459
        }
 
460
}
 
461
 
 
462
/*
 
463
  convert 16 bits/pixel data
 
464
  with alpha
 
465
  data in lsb format
 
466
*/
 
467
static void
 
468
rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
469
{
 
470
        int xx, yy;
 
471
        int width, height;
 
472
        int bpl;
 
473
 
 
474
#ifdef LITTLE
 
475
        register guint16 *s;    /* read 1 pixels at once */
 
476
#else
 
477
        register guint8 *s;
 
478
#endif
 
479
        register guint32 *o;
 
480
 
 
481
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
482
 
 
483
        width = image->width;
 
484
        height = image->height;
 
485
        bpl = image->bytes_per_line;
 
486
 
 
487
        for (yy = 0; yy < height; yy++) {
 
488
#ifdef LITTLE
 
489
                s = (guint16 *) srow;
 
490
#else
 
491
                s = (guint8 *) srow;
 
492
#endif
 
493
                o = (guint32 *) orow;
 
494
                for (xx = 0; xx < width; xx ++) {
 
495
                        register guint32 data;
 
496
                        /*  rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */
 
497
                        /*  little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */
 
498
#ifdef LITTLE
 
499
                        data = *s++;
 
500
                        *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
 
501
                                | (data & 0x7e0) << 5 | (data & 0x600) >> 1
 
502
                                | (data & 0x1f) << 19 | (data & 0x1c) << 14
 
503
                                | 0xff000000;
 
504
#else
 
505
                        /* swap endianness first */
 
506
                        data = s[0] | s[1] << 8;
 
507
                        s += 2;
 
508
                        *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
 
509
                                | (data & 0x7e0) << 13 | (data & 0x600) << 7
 
510
                                | (data & 0x1f) << 11 | (data & 0x1c) << 6
 
511
                                | 0xff;
 
512
#endif
 
513
                }
 
514
                srow += bpl;
 
515
                orow += rowstride;
 
516
        }
 
517
}
 
518
 
 
519
/*
 
520
  convert 16 bits/pixel data
 
521
  with alpha
 
522
  data in msb format
 
523
*/
 
524
static void
 
525
rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
526
{
 
527
        int xx, yy;
 
528
        int width, height;
 
529
        int bpl;
 
530
 
 
531
#ifdef LITTLE
 
532
        register guint8 *s;
 
533
#else
 
534
        register guint16 *s;    /* read 1 pixels at once */
 
535
#endif
 
536
        register guint32 *o;
 
537
 
 
538
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
539
 
 
540
        width = image->width;
 
541
        height = image->height;
 
542
        bpl = image->bytes_per_line;
 
543
 
 
544
        for (yy = 0; yy < height; yy++) {
 
545
#ifdef LITTLE
 
546
                s = srow;
 
547
#else
 
548
                s = (guint16 *) srow;
 
549
#endif
 
550
                o = (guint32 *) orow;
 
551
                for (xx = 0; xx < width; xx ++) {
 
552
                        register guint32 data;
 
553
                        /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */
 
554
                        /*  little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */
 
555
#ifdef LITTLE
 
556
                        /* swap endianness first */
 
557
                        data = s[0] | s[1] << 8;
 
558
                        s += 2;
 
559
                        *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
 
560
                                | (data & 0x7e0) << 5 | (data & 0x600) >> 1
 
561
                                | (data & 0x1f) << 19 | (data & 0x1c) << 14
 
562
                                | 0xff000000;
 
563
#else
 
564
                        data = *s++;
 
565
                        *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
 
566
                                | (data & 0x7e0) << 13 | (data & 0x600) << 7
 
567
                                | (data & 0x1f) << 11 | (data & 0x1c) << 6
 
568
                                | 0xff;
 
569
#endif
 
570
                }
 
571
                srow += bpl;
 
572
                orow += rowstride;
 
573
        }
 
574
}
 
575
 
 
576
/*
 
577
  convert 15 bits/pixel data
 
578
  no alpha
 
579
  data in lsb format
 
580
*/
 
581
static void
 
582
rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
583
{
 
584
        int xx, yy;
 
585
        int width, height;
 
586
        int bpl;
 
587
 
 
588
#ifdef LITTLE
 
589
        register guint32 *s;    /* read 2 pixels at once */
 
590
#else
 
591
        register guint8 *s;     /* read 2 pixels at once */
 
592
#endif
 
593
        register guint16 *o;
 
594
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
595
 
 
596
        width = image->width;
 
597
        height = image->height;
 
598
        bpl = image->bytes_per_line;
 
599
 
 
600
        for (yy = 0; yy < height; yy++) {
 
601
#ifdef LITTLE
 
602
                s = (guint32 *) srow;
 
603
#else
 
604
                s = srow;
 
605
#endif
 
606
                o = (guint16 *) orow;
 
607
                for (xx = 1; xx < width; xx += 2) {
 
608
                        register guint32 data;
 
609
#ifdef LITTLE
 
610
                        data = *s++;
 
611
                        *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
 
612
                                | (data & 0x3e0) << 6 | (data & 0x380) << 1;
 
613
                        *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
 
614
                                | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
 
615
                        *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
 
616
                                | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
 
617
#else
 
618
                        /* swap endianness first */
 
619
                        data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
 
620
                        s += 4;
 
621
                        *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
 
622
                                | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
 
623
                        *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
 
624
                                | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
 
625
                        *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
 
626
                                | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
 
627
#endif
 
628
                }
 
629
                /* check for last remaining pixel */
 
630
                if (width & 1) {
 
631
                        register guint16 data;
 
632
#ifdef LITTLE
 
633
                        data = *((short *) s);
 
634
#else
 
635
                        data = *((short *) s);
 
636
                        data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
 
637
#endif
 
638
                        ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
 
639
                        ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
 
640
                        ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
 
641
                }
 
642
                srow += bpl;
 
643
                orow += rowstride;
 
644
        }
 
645
}
 
646
 
 
647
/*
 
648
  convert 15 bits/pixel data
 
649
  no alpha
 
650
  data in msb format
 
651
*/
 
652
static void
 
653
rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
654
{
 
655
        int xx, yy;
 
656
        int width, height;
 
657
        int bpl;
 
658
 
 
659
#ifdef LITTLE
 
660
        register guint8 *s;     /* read 2 pixels at once */
 
661
#else
 
662
        register guint32 *s;    /* read 2 pixels at once */
 
663
#endif
 
664
        register guint16 *o;
 
665
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
666
 
 
667
        width = image->width;
 
668
        height = image->height;
 
669
        bpl = image->bytes_per_line;
 
670
 
 
671
        for (yy = 0; yy < height; yy++) {
 
672
#ifdef LITTLE
 
673
                s = srow;
 
674
#else
 
675
                s = (guint32 *) srow;
 
676
#endif
 
677
                o = (guint16 *) orow;
 
678
                for (xx = 1; xx < width; xx += 2) {
 
679
                        register guint32 data;
 
680
#ifdef LITTLE
 
681
                        /* swap endianness first */
 
682
                        data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
 
683
                        s += 4;
 
684
                        *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
 
685
                                | (data & 0x3e0) << 6 | (data & 0x380) << 1;
 
686
                        *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
 
687
                                | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
 
688
                        *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
 
689
                                | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
 
690
#else
 
691
                        data = *s++;
 
692
                        *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
 
693
                                | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
 
694
                        *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
 
695
                                | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
 
696
                        *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
 
697
                                | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
 
698
#endif
 
699
                }
 
700
                /* check for last remaining pixel */
 
701
                if (width & 1) {
 
702
                        register guint16 data;
 
703
#ifdef LITTLE
 
704
                        data = *((short *) s);
 
705
                        data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
 
706
#else
 
707
                        data = *((short *) s);
 
708
#endif
 
709
                        ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
 
710
                        ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
 
711
                        ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
 
712
                }
 
713
                srow += bpl;
 
714
                orow += rowstride;
 
715
        }
 
716
}
 
717
 
 
718
/*
 
719
  convert 15 bits/pixel data
 
720
  with alpha
 
721
  data in lsb format
 
722
*/
 
723
static void
 
724
rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
725
{
 
726
        int xx, yy;
 
727
        int width, height;
 
728
        int bpl;
 
729
 
 
730
#ifdef LITTLE
 
731
        register guint16 *s;    /* read 1 pixels at once */
 
732
#else
 
733
        register guint8 *s;
 
734
#endif
 
735
        register guint32 *o;
 
736
 
 
737
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
738
 
 
739
        width = image->width;
 
740
        height = image->height;
 
741
        bpl = image->bytes_per_line;
 
742
 
 
743
        for (yy = 0; yy < height; yy++) {
 
744
#ifdef LITTLE
 
745
                s = (guint16 *) srow;
 
746
#else
 
747
                s = srow;
 
748
#endif
 
749
                o = (guint32 *) orow;
 
750
                for (xx = 0; xx < width; xx++) {
 
751
                        register guint32 data;
 
752
                        /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
 
753
                        /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
 
754
#ifdef LITTLE
 
755
                        data = *s++;
 
756
                        *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
 
757
                                | (data & 0x3e0) << 6 | (data & 0x380) << 1
 
758
                                | (data & 0x1f) << 19 | (data & 0x1c) << 14
 
759
                                | 0xff000000;
 
760
#else
 
761
                        /* swap endianness first */
 
762
                        data = s[0] | s[1] << 8;
 
763
                        s += 2;
 
764
                        *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
 
765
                                | (data & 0x3e0) << 14 | (data & 0x380) << 9
 
766
                                | (data & 0x1f) << 11 | (data & 0x1c) << 6
 
767
                                | 0xff;
 
768
#endif
 
769
                }
 
770
                srow += bpl;
 
771
                orow += rowstride;
 
772
        }
 
773
}
 
774
 
 
775
/*
 
776
  convert 15 bits/pixel data
 
777
  with alpha
 
778
  data in msb format
 
779
*/
 
780
static void
 
781
rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
782
{
 
783
        int xx, yy;
 
784
        int width, height;
 
785
        int bpl;
 
786
 
 
787
#ifdef LITTLE
 
788
        register guint16 *s;    /* read 1 pixels at once */
 
789
#else
 
790
        register guint8 *s;
 
791
#endif
 
792
        register guint32 *o;
 
793
 
 
794
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
795
 
 
796
        width = image->width;
 
797
        height = image->height;
 
798
        bpl = image->bytes_per_line;
 
799
 
 
800
        for (yy = 0; yy < height; yy++) {
 
801
#ifdef LITTLE
 
802
                s = (guint16 *) srow;
 
803
#else
 
804
                s = srow;
 
805
#endif
 
806
                o = (guint32 *) orow;
 
807
                for (xx = 0; xx < width; xx++) {
 
808
                        register guint32 data;
 
809
                        /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
 
810
                        /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
 
811
#ifdef LITTLE
 
812
                        /* swap endianness first */
 
813
                        data = s[0] | s[1] << 8;
 
814
                        s += 2;
 
815
                        *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
 
816
                                | (data & 0x3e0) << 6 | (data & 0x380) << 1
 
817
                                | (data & 0x1f) << 19 | (data & 0x1c) << 14
 
818
                                | 0xff000000;
 
819
#else
 
820
                        data = *s++;
 
821
                        *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
 
822
                                | (data & 0x3e0) << 14 | (data & 0x380) << 9
 
823
                                | (data & 0x1f) << 11 | (data & 0x1c) << 6
 
824
                                | 0xff;
 
825
#endif
 
826
                }
 
827
                srow += bpl;
 
828
                orow += rowstride;
 
829
        }
 
830
}
 
831
 
 
832
 
 
833
static void
 
834
rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
835
{
 
836
        int xx, yy;
 
837
        int width, height;
 
838
        int bpl;
 
839
 
 
840
        guint8 *s;      /* for byte order swapping */
 
841
        guint8 *o;
 
842
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
843
 
 
844
        width = image->width;
 
845
        height = image->height;
 
846
        bpl = image->bytes_per_line;
 
847
 
 
848
        d (printf ("32 bits/pixel with alpha\n"));
 
849
 
 
850
        /* lsb data */
 
851
        for (yy = 0; yy < height; yy++) {
 
852
                s = srow;
 
853
                o = orow;
 
854
                for (xx = 0; xx < width; xx++) {
 
855
                        *o++ = s[2];
 
856
                        *o++ = s[1];
 
857
                        *o++ = s[0];
 
858
                        *o++ = 0xff;
 
859
                        s += 4;
 
860
                }
 
861
                srow += bpl;
 
862
                orow += rowstride;
 
863
        }
 
864
}
 
865
 
 
866
static void
 
867
rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
868
{
 
869
        int xx, yy;
 
870
        int width, height;
 
871
        int bpl;
 
872
 
 
873
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
874
        guint8 *o, *s;
 
875
 
 
876
        width = image->width;
 
877
        height = image->height;
 
878
        bpl = image->bytes_per_line;
 
879
 
 
880
        d (printf ("32 bit, lsb, no alpha\n"));
 
881
 
 
882
        for (yy = 0; yy < height; yy++) {
 
883
                s = srow;
 
884
                o = orow;
 
885
                for (xx = 0; xx < width; xx++) {
 
886
                        *o++ = s[2];
 
887
                        *o++ = s[1];
 
888
                        *o++ = s[0];
 
889
                        s += 4;
 
890
                }
 
891
                srow += bpl;
 
892
                orow += rowstride;
 
893
        }
 
894
}
 
895
 
 
896
static void
 
897
rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
898
{
 
899
        int xx, yy;
 
900
        int width, height;
 
901
        int bpl;
 
902
 
 
903
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
904
#ifdef LITTLE
 
905
        guint32 *o;
 
906
        guint32 *s;
 
907
#else
 
908
        guint8 *s;      /* for byte order swapping */
 
909
        guint8 *o;
 
910
#endif
 
911
 
 
912
        d (printf ("32 bit, msb, with alpha\n"));
 
913
 
 
914
        width = image->width;
 
915
        height = image->height;
 
916
        bpl = image->bytes_per_line;
 
917
 
 
918
        /* msb data */
 
919
        for (yy = 0; yy < height; yy++) {
 
920
#ifdef LITTLE
 
921
                s = (guint32 *) srow;
 
922
                o = (guint32 *) orow;
 
923
#else
 
924
                s = srow;
 
925
                o = orow;
 
926
#endif
 
927
                for (xx = 0; xx < width; xx++) {
 
928
#ifdef LITTLE
 
929
                        *o++ = s[1];
 
930
                        *o++ = s[2];
 
931
                        *o++ = s[3];
 
932
                        *o++ = 0xff;
 
933
                        s += 4;
 
934
#else
 
935
                        *o++ = (*s << 8) | 0xff; /* untested */
 
936
                        s++;
 
937
#endif
 
938
                }
 
939
                srow += bpl;
 
940
                orow += rowstride;
 
941
        }
 
942
}
 
943
 
 
944
static void
 
945
rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
 
946
{
 
947
        int xx, yy;
 
948
        int width, height;
 
949
        int bpl;
 
950
 
 
951
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
952
        guint8 *s;
 
953
        guint8 *o;
 
954
 
 
955
        d (printf ("32 bit, msb, no alpha\n"));
 
956
 
 
957
        width = image->width;
 
958
        height = image->height;
 
959
        bpl = image->bytes_per_line;
 
960
 
 
961
        for (yy = 0; yy < height; yy++) {
 
962
                s = srow;
 
963
                o = orow;
 
964
                for (xx = 0; xx < width; xx++) {
 
965
                        *o++ = s[1];
 
966
                        *o++ = s[2];
 
967
                        *o++ = s[3];
 
968
                        s += 4;
 
969
                }
 
970
                srow += bpl;
 
971
                orow += rowstride;
 
972
        }
 
973
}
 
974
 
 
975
/*
 
976
  This should work correctly with any display/any endianness, but will probably
 
977
  run quite slow
 
978
*/
 
979
static void
 
980
convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha)
 
981
{
 
982
        int xx, yy;
 
983
        int width, height;
 
984
        int bpl;
 
985
        guint8 *srow = (guint8 *)image->data, *orow = pixels;
 
986
        guint8 *o;
 
987
        guint32 pixel;
 
988
        Visual *v;
 
989
        guint8 component;
 
990
        int i;
 
991
        int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec;
 
992
 
 
993
        width = image->width;
 
994
        height = image->height;
 
995
        bpl = image->bytes_per_line;
 
996
        v = cmap->visual;
 
997
 
 
998
        visual_decompose_mask (v->red_mask, &red_shift, &red_prec);
 
999
        visual_decompose_mask (v->green_mask, &green_shift, &green_prec);
 
1000
        visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec);
 
1001
 
 
1002
        d(printf("rgb  mask/shift/prec = %x:%x:%x %d:%d:%d  %d:%d:%d\n",
 
1003
                 v->red_mask, v->green_mask, v->blue_mask,
 
1004
                 red_shift, green_shift, blue_shift,
 
1005
                 red_prec, green_prec, blue_prec));
 
1006
 
 
1007
        for (yy = 0; yy < height; yy++) {
 
1008
                o = orow;
 
1009
                for (xx = 0; xx < width; xx++) {
 
1010
                        pixel = XGetPixel (image, xx, yy);
 
1011
                        switch (v->class) {
 
1012
                                /* I assume this is right for static & greyscale's too? */
 
1013
                        case StaticGray:
 
1014
                        case GrayScale:
 
1015
                        case StaticColor:
 
1016
                        case PseudoColor:
 
1017
                                *o++ = cmap->colors[pixel].red;
 
1018
                                *o++ = cmap->colors[pixel].green;
 
1019
                                *o++ = cmap->colors[pixel].blue;
 
1020
                                break;
 
1021
                        case TrueColor:
 
1022
                                /* This is odd because it must sometimes shift left (otherwise
 
1023
                                   I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic
 
1024
                                   should work for all bit sizes/shifts/etc. */
 
1025
                                component = 0;
 
1026
                                for (i = 24; i < 32; i += red_prec)
 
1027
                                        component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i;
 
1028
                                *o++ = component;
 
1029
                                component = 0;
 
1030
                                for (i = 24; i < 32; i += green_prec)
 
1031
                                        component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i;
 
1032
                                *o++ = component;
 
1033
                                component = 0;
 
1034
                                for (i = 24; i < 32; i += blue_prec)
 
1035
                                        component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i;
 
1036
                                *o++ = component;
 
1037
                                break;
 
1038
                        case DirectColor:
 
1039
                                *o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red;
 
1040
                                *o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green;
 
1041
                                *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue;
 
1042
                                break;
 
1043
                        }
 
1044
                        if (alpha)
 
1045
                                *o++ = 0xff;
 
1046
                }
 
1047
                srow += bpl;
 
1048
                orow += rowstride;
 
1049
        }
 
1050
}
 
1051
 
 
1052
typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap);
 
1053
 
 
1054
static const cfunc convert_map[] = {
 
1055
        rgb1,rgb1,rgb1a,rgb1a,
 
1056
        rgb8,rgb8,rgb8a,rgb8a,
 
1057
        rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
 
1058
        rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
 
1059
        rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
 
1060
};
 
1061
 
 
1062
/*
 
1063
  perform actual conversion
 
1064
 
 
1065
  If we can, try and use the optimised code versions, but as a default
 
1066
  fallback, and always for direct colour, use the generic/slow but complete
 
1067
  conversion function.
 
1068
*/
 
1069
static void
 
1070
rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap)
 
1071
{
 
1072
        int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
 
1073
        int bank=5;             /* default fallback converter */
 
1074
        Visual *v = cmap->visual;
 
1075
 
 
1076
        d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
 
1077
        d(printf("image depth = %d, bpp = %d\n", image->depth, image->bits_per_pixel));
 
1078
 
 
1079
        switch (v->class) {
 
1080
                                /* I assume this is right for static & greyscale's too? */
 
1081
        case StaticGray:
 
1082
        case GrayScale:
 
1083
        case StaticColor:
 
1084
        case PseudoColor:
 
1085
                switch (image->bits_per_pixel) {
 
1086
                case 1:
 
1087
                        bank = 0;
 
1088
                        break;
 
1089
                case 8:
 
1090
                        bank = 1;
 
1091
                        break;
 
1092
                }
 
1093
                break;
 
1094
        case TrueColor:
 
1095
                switch (image->depth) {
 
1096
                case 15:
 
1097
                        if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
 
1098
                            && image->bits_per_pixel == 16)
 
1099
                                bank = 2;
 
1100
                        break;
 
1101
                case 16:
 
1102
                        if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
 
1103
                            && image->bits_per_pixel == 16)
 
1104
                                bank = 3;
 
1105
                        break;
 
1106
                case 24:
 
1107
                case 32:
 
1108
                        if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
 
1109
                            && image->bits_per_pixel == 32)
 
1110
                                bank = 4;
 
1111
                        break;
 
1112
                }
 
1113
                break;
 
1114
        case DirectColor:
 
1115
                /* always use the slow version */
 
1116
                break;
 
1117
        }
 
1118
 
 
1119
        d(printf("converting using conversion function in bank %d\n", bank));
 
1120
 
 
1121
        if (bank==5) {
 
1122
                convert_real_slow(image, pixels, rowstride, cmap, alpha);
 
1123
        } else {
 
1124
                index |= bank << 2;
 
1125
                (* convert_map[index]) (image, pixels, rowstride, cmap);
 
1126
        }
 
1127
}
 
1128
 
 
1129
static gboolean
 
1130
xlib_window_is_viewable (Window w)
 
1131
{
 
1132
        XWindowAttributes wa;
 
1133
 
 
1134
        while (w != 0) {
 
1135
                Window parent, root, *children;
 
1136
                guint nchildren;
 
1137
 
 
1138
                XGetWindowAttributes (gdk_pixbuf_dpy, w, &wa);
 
1139
                if (wa.map_state != IsViewable)
 
1140
                        return FALSE;
 
1141
 
 
1142
                if (!XQueryTree (gdk_pixbuf_dpy, w, &root,
 
1143
                                 &parent, &children, &nchildren))
 
1144
                        return FALSE;
 
1145
 
 
1146
                if (nchildren > 0)
 
1147
                        XFree (children);
 
1148
 
 
1149
                if ((parent == root) || (w == root))
 
1150
                        return TRUE;
 
1151
 
 
1152
                w = parent;
 
1153
        }
 
1154
 
 
1155
        return FALSE;
 
1156
}
 
1157
 
 
1158
static gint
 
1159
xlib_window_get_origin (Window w, gint *x, gint *y)
 
1160
{
 
1161
        Window child;
 
1162
        return XTranslateCoordinates (gdk_pixbuf_dpy, w,
 
1163
                                      RootWindow (gdk_pixbuf_dpy,
 
1164
                                                  gdk_pixbuf_screen),
 
1165
                                      0, 0, x, y, &child);
 
1166
}
 
1167
 
 
1168
/* Exported functions */
 
1169
 
 
1170
/**
 
1171
 * gdk_pixbuf_xlib_get_from_drawable:
 
1172
 * @dest: Destination pixbuf, or NULL if a new pixbuf should be created.
 
1173
 * @src: Source drawable.
 
1174
 * @cmap: A colormap if @src is a pixmap.  If it is a window, this argument will
 
1175
 * be ignored.
 
1176
 * @visual: A visual if @src is a pixmap.  If it is a window, this argument will
 
1177
 * be ignored.
 
1178
 * @src_x: Source X coordinate within drawable.
 
1179
 * @src_y: Source Y coordinate within drawable.
 
1180
 * @dest_x: Destination X coordinate in pixbuf, or 0 if @dest is NULL.
 
1181
 * @dest_y: Destination Y coordinate in pixbuf, or 0 if @dest is NULL.
 
1182
 * @width: Width in pixels of region to get.
 
1183
 * @height: Height in pixels of region to get.
 
1184
 *
 
1185
 * Transfers image data from a Gdk drawable and converts it to an RGB(A)
 
1186
 * representation inside a GdkPixbuf.
 
1187
 *
 
1188
 * If the drawable @src is a pixmap, then a suitable colormap must be specified,
 
1189
 * since pixmaps are just blocks of pixel data without an associated colormap.
 
1190
 * If the drawable is a window, the @cmap argument will be ignored and the
 
1191
 * window's own colormap will be used instead.
 
1192
 *
 
1193
 * If the specified destination pixbuf @dest is #NULL, then this function will
 
1194
 * create an RGB pixbuf with 8 bits per channel and no alpha, with the same size
 
1195
 * specified by the @width and @height arguments.  In this case, the @dest_x and
 
1196
 * @dest_y arguments must be specified as 0, otherwise the function will return
 
1197
 * #NULL.  If the specified destination pixbuf is not NULL and it contains alpha
 
1198
 * information, then the filled pixels will be set to full opacity.
 
1199
 *
 
1200
 * If the specified drawable is a pixmap, then the requested source rectangle
 
1201
 * must be completely contained within the pixmap, otherwise the function will
 
1202
 * return #NULL.
 
1203
 *
 
1204
 * If the specified drawable is a window, then it must be viewable, i.e. all of
 
1205
 * its ancestors up to the root window must be mapped.  Also, the specified
 
1206
 * source rectangle must be completely contained within the window and within
 
1207
 * the screen.  If regions of the window are obscured by noninferior windows, the
 
1208
 * contents of those regions are undefined.  The contents of regions obscured by
 
1209
 * inferior windows of a different depth than that of the source window will also
 
1210
 * be undefined.
 
1211
 *
 
1212
 * Return value: The same pixbuf as @dest if it was non-NULL, or a newly-created
 
1213
 * pixbuf with a reference count of 1 if no destination pixbuf was specified; in
 
1214
 * the latter case, NULL will be returned if not enough memory could be
 
1215
 * allocated for the pixbuf to be created.
 
1216
 **/
 
1217
GdkPixbuf *
 
1218
gdk_pixbuf_xlib_get_from_drawable (GdkPixbuf *dest,
 
1219
                                   Drawable src,
 
1220
                                   Colormap cmap, Visual *visual,
 
1221
                                   int src_x, int src_y,
 
1222
                                   int dest_x, int dest_y,
 
1223
                                   int width, int height)
 
1224
{
 
1225
        guint src_width, src_height;
 
1226
        XImage *image;
 
1227
        int rowstride, bpp, alpha;
 
1228
        XWindowAttributes wa;
 
1229
        xlib_colormap *x_cmap;
 
1230
        gboolean is_pixmap;
 
1231
 
 
1232
        /* General sanity checks */
 
1233
 
 
1234
        g_return_val_if_fail (src != 0, NULL);
 
1235
 
 
1236
        is_pixmap = drawable_is_pixmap (src);
 
1237
 
 
1238
        if (is_pixmap) {
 
1239
                g_return_val_if_fail (cmap != 0, NULL);
 
1240
                g_return_val_if_fail (visual != NULL, NULL);
 
1241
        }
 
1242
        else
 
1243
                g_return_val_if_fail (xlib_window_is_viewable (src), NULL);
 
1244
 
 
1245
        if (!dest)
 
1246
                g_return_val_if_fail (dest_x == 0 && dest_y == 0, NULL);
 
1247
        else {
 
1248
                g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL);
 
1249
                g_return_val_if_fail (gdk_pixbuf_get_n_channels (dest) == 3
 
1250
                                      || gdk_pixbuf_get_n_channels (dest) == 4, NULL);
 
1251
                g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL);
 
1252
        }
 
1253
 
 
1254
        /* Coordinate sanity checks */
 
1255
 
 
1256
        if (!is_pixmap) {
 
1257
            XGetWindowAttributes (gdk_pixbuf_dpy, src, &wa);
 
1258
            src_width = wa.width;
 
1259
            src_height = wa.height;
 
1260
        } else {
 
1261
            Window root;
 
1262
            int tx, ty;
 
1263
            guint bwidth, depth;
 
1264
            XGetGeometry (gdk_pixbuf_dpy, src, &root, &tx, &ty,
 
1265
                          &src_width, &src_height, &bwidth, &depth);
 
1266
        }
 
1267
 
 
1268
        g_return_val_if_fail (src_x >= 0 && src_y >= 0, NULL);
 
1269
        g_return_val_if_fail (src_x + width <= src_width
 
1270
                              && src_y + height <= src_height, NULL);
 
1271
 
 
1272
        if (dest) {
 
1273
                g_return_val_if_fail (dest_x >= 0 && dest_y >= 0, NULL);
 
1274
                g_return_val_if_fail (dest_x + width <= gdk_pixbuf_get_width (dest), NULL);
 
1275
                g_return_val_if_fail (dest_y + height <= gdk_pixbuf_get_height (dest), NULL);
 
1276
        }
 
1277
 
 
1278
        if (!is_pixmap) {
 
1279
                int ret;
 
1280
                int src_xorigin, src_yorigin;
 
1281
                int screen_width, screen_height;
 
1282
                int screen_srcx, screen_srcy;
 
1283
 
 
1284
                ret = xlib_window_get_origin (src, &src_xorigin, &src_yorigin);
 
1285
                g_return_val_if_fail (ret != FALSE, NULL);
 
1286
 
 
1287
                screen_width = DisplayWidth (gdk_pixbuf_dpy, gdk_pixbuf_screen);
 
1288
                screen_height = DisplayHeight (gdk_pixbuf_dpy, gdk_pixbuf_screen);
 
1289
 
 
1290
                screen_srcx = src_xorigin + src_x;
 
1291
                screen_srcy = src_yorigin + src_y;
 
1292
 
 
1293
                g_return_val_if_fail (screen_srcx >= 0 && screen_srcy >= 0, NULL);
 
1294
                g_return_val_if_fail (screen_srcx + width <= screen_width, NULL);
 
1295
                g_return_val_if_fail (screen_srcy + height <= screen_height, NULL);
 
1296
        }
 
1297
 
 
1298
        /* Get Image in ZPixmap format (packed bits). */
 
1299
        image = XGetImage (gdk_pixbuf_dpy, src, src_x, src_y,
 
1300
                           width, height, AllPlanes, ZPixmap);
 
1301
        g_return_val_if_fail (image != NULL, NULL);
 
1302
 
 
1303
        /* Create the pixbuf if needed */
 
1304
        if (!dest) {
 
1305
                dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
 
1306
                                       FALSE, 8, width, height);
 
1307
                if (!dest) {
 
1308
                        XDestroyImage (image);
 
1309
                        return NULL;
 
1310
                }
 
1311
        }
 
1312
 
 
1313
        /* Get the colormap if needed */
 
1314
        if (!is_pixmap)
 
1315
        {
 
1316
                cmap = wa.colormap;
 
1317
                visual = wa.visual;
 
1318
        }
 
1319
 
 
1320
        x_cmap = xlib_get_colormap (cmap, visual);
 
1321
 
 
1322
        alpha = gdk_pixbuf_get_has_alpha (dest);
 
1323
        rowstride = gdk_pixbuf_get_rowstride (dest);
 
1324
        bpp = alpha ? 4 : 3;
 
1325
 
 
1326
        /* we offset into the image data based on the position we are retrieving from */
 
1327
        rgbconvert (image, gdk_pixbuf_get_pixels (dest) +
 
1328
                    (dest_y * rowstride) + (dest_x * bpp),
 
1329
                    rowstride,
 
1330
                    alpha,
 
1331
                    x_cmap);
 
1332
 
 
1333
        xlib_colormap_free (x_cmap);
 
1334
        XDestroyImage (image);
 
1335
 
 
1336
        return dest;
 
1337
}