Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / xpixmap.c
1 /* xpixmap.c - Make RImage from Pixmap or XImage
2  *
3  * Raster graphics library
4  *
5  * Copyright (c) 1997-2003 Alfredo K. Kojima
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <config.h>
23
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30
31 #include "wraster.h"
32
33 static int get_shifts(unsigned long mask)
34 {
35         int i = 0;
36
37         while (mask) {
38                 mask >>= 1;
39                 i++;
40         }
41         return i;
42 }
43
44 #define NORMALIZE_RED(pixel)    ((rshift>0) ? ((pixel) & rmask) >> rshift \
45     : ((pixel) & rmask) << -rshift)
46 #define NORMALIZE_GREEN(pixel)  ((gshift>0) ? ((pixel) & gmask) >> gshift \
47     : ((pixel) & gmask) << -gshift)
48 #define NORMALIZE_BLUE(pixel)   ((bshift>0) ? ((pixel) & bmask) >> bshift \
49     : ((pixel) & bmask) << -bshift)
50
51 RImage *RCreateImageFromXImage(RContext * context, XImage * image, XImage * mask)
52 {
53         RImage *img;
54         int x, y;
55         unsigned long pixel;
56         unsigned char *data;
57         int rshift, gshift, bshift;
58         int rmask, gmask, bmask;
59
60         assert(image != NULL);
61         assert(image->format == ZPixmap);
62         assert(!mask || mask->format == ZPixmap);
63
64         img = RCreateImage(image->width, image->height, mask != NULL);
65         if (!img) {
66                 return NULL;
67         }
68
69         /* I don't know why, but XGetImage() for pixmaps don't set the
70          * {red,green,blue}_mask values correctly.
71          */
72         if (context->depth == image->depth) {
73                 rmask = context->visual->red_mask;
74                 gmask = context->visual->green_mask;
75                 bmask = context->visual->blue_mask;
76         } else {
77                 rmask = image->red_mask;
78                 gmask = image->green_mask;
79                 bmask = image->blue_mask;
80         }
81
82         /* how many bits to shift to normalize the color into 8bpp */
83         rshift = get_shifts(rmask) - 8;
84         gshift = get_shifts(gmask) - 8;
85         bshift = get_shifts(bmask) - 8;
86
87         data = img->data;
88
89         if (image->depth == 1) {
90                 for (y = 0; y < image->height; y++) {
91                         for (x = 0; x < image->width; x++) {
92                                 pixel = XGetPixel(image, x, y);
93                                 if (pixel) {
94                                         *data++ = 0;
95                                         *data++ = 0;
96                                         *data++ = 0;
97                                 } else {
98                                         *data++ = 0xff;
99                                         *data++ = 0xff;
100                                         *data++ = 0xff;
101                                 }
102                                 if (mask)
103                                         data++;
104                         }
105                 }
106         } else {
107                 for (y = 0; y < image->height; y++) {
108                         for (x = 0; x < image->width; x++) {
109                                 pixel = XGetPixel(image, x, y);
110                                 *(data++) = NORMALIZE_RED(pixel);
111                                 *(data++) = NORMALIZE_GREEN(pixel);
112                                 *(data++) = NORMALIZE_BLUE(pixel);
113                                 if (mask)
114                                         data++;
115                         }
116                 }
117         }
118
119 #define MIN(a,b) ((a)<(b)?(a):(b))
120         if (mask) {
121                 data = img->data + 3;   /* Skip R, G & B */
122                 for (y = 0; y < MIN(mask->height, image->height); y++) {
123                         for (x = 0; x < MIN(mask->width, image->width); x++) {
124                                 if (mask->width <= image->width && XGetPixel(mask, x, y)) {
125                                         *data = 0xff;
126                                 } else {
127                                         *data = 0;
128                                 }
129                                 data += 4;
130                         }
131                         for (; x < image->width; x++) {
132                                 *data = 0;
133                                 data += 4;
134                         }
135                 }
136                 for (; y < image->height; y++) {
137                         for (x = 0; x < image->width; x++) {
138                                 *data = 0;
139                                 data += 4;
140                         }
141                 }
142         }
143         return img;
144 }
145
146 RImage *RCreateImageFromDrawable(RContext * context, Drawable drawable, Pixmap mask)
147 {
148         RImage *image;
149         XImage *pimg, *mimg;
150         unsigned int w, h, bar;
151         int foo;
152         Window baz;
153
154         assert(drawable != None);
155
156         if (!XGetGeometry(context->dpy, drawable, &baz, &foo, &foo, &w, &h, &bar, &bar)) {
157                 printf("wrlib: invalid window or pixmap passed to RCreateImageFromPixmap\n");
158                 return NULL;
159         }
160         pimg = XGetImage(context->dpy, drawable, 0, 0, w, h, AllPlanes, ZPixmap);
161
162         if (!pimg) {
163                 RErrorCode = RERR_XERROR;
164                 return NULL;
165         }
166         mimg = NULL;
167         if (mask) {
168                 if (XGetGeometry(context->dpy, mask, &baz, &foo, &foo, &w, &h, &bar, &bar)) {
169                         mimg = XGetImage(context->dpy, mask, 0, 0, w, h, AllPlanes, ZPixmap);
170                 }
171         }
172
173         image = RCreateImageFromXImage(context, pimg, mimg);
174
175         XDestroyImage(pimg);
176         if (mimg)
177                 XDestroyImage(mimg);
178
179         return image;
180 }