I was trying to optimize this w/o using this, hope the change is right.
[wmaker-crm.git] / wrlib / xpixmap.c
blobd1f4a1a66b556dae9bd4928c9a8303e742e7db8f
1 /* xpixmap.c - Make RImage from Pixmap or XImage
2 *
3 * Raster graphics library
5 * Copyright (c) 1997 Alfredo K. Kojima
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.
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.
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.
23 #include <config.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
32 #include "wraster.h"
36 static int
37 get_shifts(unsigned long mask)
39 int i=0;
41 while (mask) {
42 mask>>=1;
43 i++;
45 return i;
48 #define NORMALIZE_RED(pixel) ((rshift>0) ? ((pixel) & rmask) >> rshift \
49 : ((pixel) & rmask) << -rshift)
50 #define NORMALIZE_GREEN(pixel) ((gshift>0) ? ((pixel) & gmask) >> gshift \
51 : ((pixel) & gmask) << -gshift)
52 #define NORMALIZE_BLUE(pixel) ((bshift>0) ? ((pixel) & bmask) >> bshift \
53 : ((pixel) & bmask) << -bshift)
55 RImage*
56 RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
58 RImage *img;
59 int x, y;
60 unsigned long pixel;
61 unsigned char *data;
62 int rshift, gshift, bshift;
63 int rmask, gmask, bmask;
65 assert(image!=NULL);
66 assert(image->format==ZPixmap);
67 assert(!mask || mask->format==ZPixmap);
69 img = RCreateImage(image->width, image->height, mask!=NULL);
70 if (!img) {
71 return NULL;
75 /* I don't know why, but XGetImage() for pixmaps don't set the
76 * {red,green,blue}_mask values correctly.
77 */
78 if (context->depth==image->depth) {
79 rmask = context->visual->red_mask;
80 gmask = context->visual->green_mask;
81 bmask = context->visual->blue_mask;
82 } else {
83 rmask = image->red_mask;
84 gmask = image->green_mask;
85 bmask = image->blue_mask;
88 /* how many bits to shift to normalize the color into 8bpp */
89 rshift = get_shifts(rmask) - 8;
90 gshift = get_shifts(gmask) - 8;
91 bshift = get_shifts(bmask) - 8;
93 data = img->data;
95 if (image->depth==1) {
96 if (mask) {
97 for (y = 0; y < image->height; y++) {
98 for (x = 0; x < image->width; x++) {
99 pixel = XGetPixel(image, x, y);
100 if (pixel) {
101 *data++ = 0;
102 *data++ = 0;
103 *data++ = 0;
104 } else {
105 *data++ = 0xff;
106 *data++ = 0xff;
107 *data++ = 0xff;
109 data++;
112 } else {
113 for (y = 0; y < image->height; y++) {
114 for (x = 0; x < image->width; x++) {
115 pixel = XGetPixel(image, x, y);
116 if (pixel) {
117 *data++ = 0;
118 *data++ = 0;
119 *data++ = 0;
120 } else {
121 *data++ = 0xff;
122 *data++ = 0xff;
123 *data++ = 0xff;
128 } else {
129 if (mask) {
130 for (y = 0; y < image->height; y++) {
131 for (x = 0; x < image->width; x++) {
132 pixel = XGetPixel(image, x, y);
133 *(data++) = NORMALIZE_RED(pixel);
134 *(data++) = NORMALIZE_GREEN(pixel);
135 *(data++) = NORMALIZE_BLUE(pixel);
136 data++;
139 } else {
140 for (y = 0; y < image->height; y++) {
141 for (x = 0; x < image->width; x++) {
142 pixel = XGetPixel(image, x, y);
143 *(data++) = NORMALIZE_RED(pixel);
144 *(data++) = NORMALIZE_GREEN(pixel);
145 *(data++) = NORMALIZE_BLUE(pixel);
151 #define MIN(a,b) ((a)<(b)?(a):(b))
152 if (mask) {
153 data = img->data;
154 data += 3; /* Skip R, G & B */
155 for (y = 0; y < MIN(mask->height, image->height); y++) {
156 for (x = 0; x < MIN(mask->width, image->width); x++) {
157 if (mask->width <= image->width && XGetPixel(mask, x, y)) {
158 *data = 0xff;
159 } else {
160 *data = 0;
162 data += 4;
164 for (; x < image->width; x++) {
165 *data = 0;
166 data += 4;
169 for (; y < image->height; y++) {
170 for (x = 0; x < image->width; x++) {
171 *data = 0;
172 data += 4;
176 return img;
181 RImage*
182 RCreateImageFromDrawable(RContext *context, Drawable drawable, Pixmap mask)
184 RImage *image;
185 XImage *pimg, *mimg;
186 unsigned int w, h, bar;
187 int foo;
188 Window baz;
191 assert(drawable!=None);
193 if (!XGetGeometry(context->dpy, drawable, &baz, &foo, &foo,
194 &w, &h, &bar, &bar)) {
195 printf("wrlib:invalid window or pixmap passed to RCreateImageFromPixmap\n");
196 return NULL;
198 pimg = XGetImage(context->dpy, drawable, 0, 0, w, h, AllPlanes,
199 ZPixmap);
201 if (!pimg) {
202 RErrorCode = RERR_XERROR;
203 return NULL;
205 mimg = NULL;
206 if (mask) {
207 if (XGetGeometry(context->dpy, mask, &baz, &foo, &foo,
208 &w, &h, &bar, &bar)) {
209 mimg = XGetImage(context->dpy, mask, 0, 0, w, h, AllPlanes,
210 ZPixmap);
214 image = RCreateImageFromXImage(context, pimg, mimg);
216 XDestroyImage(pimg);
217 if (mimg)
218 XDestroyImage(mimg);
220 return image;