updated po files, fixed some bugs
[wmaker-crm.git] / wrlib / convert.c
blobbab3cbb2096f098b67d78f11bdf9e0adb5ddeb93
1 /* convert.c - convert RImage to Pixmap
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.
21 #include <config.h>
23 /* AIX requires this to be the first thing in the file. */
24 #ifdef __GNUC__
25 # define alloca __builtin_alloca
26 #else
27 # if HAVE_ALLOCA_H
28 # include <alloca.h>
29 # else
30 # ifdef _AIX
31 # pragma alloca
32 # else
33 # ifndef alloca /* predefined by HP cc +Olibcalls */
34 char *alloca ();
35 # endif
36 # endif
37 # endif
38 #endif
41 #include <X11/Xlib.h>
42 #include <X11/Xutil.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
47 #include <assert.h>
49 #include "wraster.h"
51 #ifdef XSHM
52 Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage);
54 #endif
57 typedef struct RConversionTable {
58 unsigned short table[256];
59 unsigned short index;
60 struct RConversionTable *next;
61 } RConversionTable;
64 static RConversionTable *conversionTable = NULL;
67 static unsigned short*
68 computeTable(unsigned short mask)
70 RConversionTable *tmp = conversionTable;
71 int i;
73 while (tmp) {
74 if (tmp->index == mask)
75 break;
76 tmp = tmp->next;
79 if (tmp)
80 return tmp->table;
82 tmp = (RConversionTable *)malloc(sizeof(RConversionTable));
83 if (tmp == NULL)
84 return NULL;
86 for (i=0;i<256;i++)
87 tmp->table[i] = (i*mask + 0x7f)/0xff;
89 tmp->index = mask;
90 tmp->next = conversionTable;
91 conversionTable = tmp;
92 return tmp->table;
97 static RXImage*
98 image2TrueColorD16(RContext *ctx, RImage *image)
100 RXImage *ximg;
101 register int x, y, r, g, b;
102 unsigned char *red, *grn, *blu;
103 unsigned short rmask, gmask, bmask;
104 unsigned short roffs, goffs, boffs;
105 unsigned short *rtable, *gtable, *btable;
106 int ofs;
108 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
109 if (!ximg) {
110 return NULL;
113 red = image->data[0];
114 grn = image->data[1];
115 blu = image->data[2];
117 roffs = ctx->red_offset;
118 goffs = ctx->green_offset;
119 boffs = ctx->blue_offset;
121 rmask = ctx->visual->red_mask >> roffs;
122 gmask = ctx->visual->green_mask >> goffs;
123 bmask = ctx->visual->blue_mask >> boffs;
125 rtable = computeTable(rmask);
126 gtable = computeTable(gmask);
127 btable = computeTable(bmask);
129 if (rtable==NULL || gtable==NULL || btable==NULL) {
130 RErrorCode = RERR_NOMEMORY;
131 RDestroyXImage(ctx, ximg);
132 return NULL;
136 /* dither */
137 short *rerr, *gerr, *berr;
138 short *nrerr, *ngerr, *nberr;
139 short *terr;
140 unsigned short *dataP;
141 int line_offset;
142 int rer, ger, ber;
143 const int dr=0xff/rmask;
144 const int dg=0xff/gmask;
145 const int db=0xff/bmask;
147 rerr = (short*)alloca((image->width+2)*sizeof(short));
148 gerr = (short*)alloca((image->width+2)*sizeof(short));
149 berr = (short*)alloca((image->width+2)*sizeof(short));
150 nrerr = (short*)alloca((image->width+2)*sizeof(short));
151 ngerr = (short*)alloca((image->width+2)*sizeof(short));
152 nberr = (short*)alloca((image->width+2)*sizeof(short));
153 if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
154 RErrorCode = RERR_NOMEMORY;
155 RDestroyXImage(ctx, ximg);
156 return NULL;
158 for (x=0; x<image->width; x++) {
159 rerr[x] = red[x];
160 gerr[x] = grn[x];
161 berr[x] = blu[x];
163 rerr[x] = gerr[x] = berr[x] = 0;
165 dataP = (unsigned short*)ximg->image->data;
166 line_offset = ximg->image->bytes_per_line - image->width * 2;
168 /* convert and dither the image to XImage */
169 for (y=0, ofs=0; y<image->height; y++) {
170 if (y<image->height-1) {
171 int x1;
172 for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
173 nrerr[x] = red[x1];
174 ngerr[x] = grn[x1];
175 nberr[x] = blu[x1];
177 /* last column */
178 x1--;
179 nrerr[x] = red[x1];
180 ngerr[x] = grn[x1];
181 nberr[x] = blu[x1];
183 for (x=0; x<image->width; x++) {
184 /* reduce pixel */
185 if (rerr[x]>0xff) rerr[x]=0xff; else if (rerr[x]<0) rerr[x]=0;
186 if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
187 if (berr[x]>0xff) berr[x]=0xff; else if (berr[x]<0) berr[x]=0;
189 r = rtable[rerr[x]];
190 g = gtable[gerr[x]];
191 b = btable[berr[x]];
193 *(dataP++) = (r<<roffs) | (g<<goffs) | (b<<boffs);
195 /* calc error */
196 rer = rerr[x] - r*dr;
197 ger = gerr[x] - g*dg;
198 ber = berr[x] - b*db;
200 /* distribute error */
201 r = (rer*3)/8;
202 g = (ger*3)/8;
203 b = (ber*3)/8;
204 /* x+1, y */
205 rerr[x+1]+=r;
206 gerr[x+1]+=g;
207 berr[x+1]+=b;
208 /* x, y+1 */
209 nrerr[x]+=r;
210 ngerr[x]+=g;
211 nberr[x]+=b;
212 /* x+1, y+1 */
213 nrerr[x+1]+=rer-2*r;
214 ngerr[x+1]+=ger-2*g;
215 nberr[x+1]+=ber-2*b;
217 ofs += image->width;
218 /*(char*)dataP += line_offset;*/
219 dataP = (unsigned short *)((char *)dataP + line_offset);
221 /* skip to next line */
222 terr = rerr;
223 rerr = nrerr;
224 nrerr = terr;
226 terr = gerr;
227 gerr = ngerr;
228 ngerr = terr;
230 terr = berr;
231 berr = nberr;
232 nberr = terr;
235 return ximg;
239 static RXImage*
240 image2TrueColor(RContext *ctx, RImage *image)
242 RXImage *ximg;
243 register int x, y, r, g, b;
244 unsigned char *red, *grn, *blu;
245 unsigned long pixel;
246 unsigned short rmask, gmask, bmask;
247 unsigned short roffs, goffs, boffs;
248 unsigned short *rtable, *gtable, *btable;
249 int ofs;
251 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
252 if (!ximg) {
253 return NULL;
256 red = image->data[0];
257 grn = image->data[1];
258 blu = image->data[2];
260 roffs = ctx->red_offset;
261 goffs = ctx->green_offset;
262 boffs = ctx->blue_offset;
264 rmask = ctx->visual->red_mask >> roffs;
265 gmask = ctx->visual->green_mask >> goffs;
266 bmask = ctx->visual->blue_mask >> boffs;
268 #if 0
269 /* this do not seem to increase speed. Only 0.06 second faster in
270 * rendering a 800x600 image to pixmap. 1.12 sec instead of 1.18.
271 * But does not require a 256*256*256 lookup table.
273 if (ctx->depth==24) {
274 #ifdef DEBUG
275 puts("true color match for 24bpp");
276 #endif
277 for (y=0; y < image->height; y++) {
278 for (x=0; x < image->width; x++) {
279 pixel = (*(red++)<<roffs) | (*(grn++)<<goffs) | (*(blu++)<<boffs);
280 XPutPixel(ximg->image, x, y, pixel);
283 return ximg;
285 #endif
287 rtable = computeTable(rmask);
288 gtable = computeTable(gmask);
289 btable = computeTable(bmask);
291 if (rtable==NULL || gtable==NULL || btable==NULL) {
292 RErrorCode = RERR_NOMEMORY;
293 RDestroyXImage(ctx, ximg);
294 return NULL;
297 if (ctx->attribs->render_mode==RBestMatchRendering) {
298 /* fake match */
299 #ifdef DEBUG
300 puts("true color match");
301 #endif
302 for (y=0, ofs=0; y < image->height; y++) {
303 for (x=0; x < image->width; x++, ofs++) {
304 /* reduce pixel */
305 r = rtable[red[ofs]];
306 g = gtable[grn[ofs]];
307 b = btable[blu[ofs]];
308 pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
309 XPutPixel(ximg->image, x, y, pixel);
312 } else {
313 /* dither */
314 short *rerr, *gerr, *berr;
315 short *nrerr, *ngerr, *nberr;
316 short *terr;
317 int rer, ger, ber;
318 const int dr=0xff/rmask;
319 const int dg=0xff/gmask;
320 const int db=0xff/bmask;
322 #ifdef DEBUG
323 puts("true color dither");
324 #endif
325 rerr = (short*)alloca((image->width+2)*sizeof(short));
326 gerr = (short*)alloca((image->width+2)*sizeof(short));
327 berr = (short*)alloca((image->width+2)*sizeof(short));
328 nrerr = (short*)alloca((image->width+2)*sizeof(short));
329 ngerr = (short*)alloca((image->width+2)*sizeof(short));
330 nberr = (short*)alloca((image->width+2)*sizeof(short));
331 if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
332 RErrorCode = RERR_NOMEMORY;
333 RDestroyXImage(ctx, ximg);
334 return NULL;
336 for (x=0; x<image->width; x++) {
337 rerr[x] = red[x];
338 gerr[x] = grn[x];
339 berr[x] = blu[x];
341 rerr[x] = gerr[x] = berr[x] = 0;
342 /* convert and dither the image to XImage */
343 for (y=0, ofs=0; y<image->height; y++) {
344 if (y<image->height-1) {
345 int x1;
346 for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
347 nrerr[x] = red[x1];
348 ngerr[x] = grn[x1];
349 nberr[x] = blu[x1];
351 /* last column */
352 x1--;
353 nrerr[x] = red[x1];
354 ngerr[x] = grn[x1];
355 nberr[x] = blu[x1];
357 for (x=0; x<image->width; x++) {
358 /* reduce pixel */
359 if (rerr[x]>0xff) rerr[x]=0xff; else if (rerr[x]<0) rerr[x]=0;
360 if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
361 if (berr[x]>0xff) berr[x]=0xff; else if (berr[x]<0) berr[x]=0;
363 r = rtable[rerr[x]];
364 g = gtable[gerr[x]];
365 b = btable[berr[x]];
367 pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
368 XPutPixel(ximg->image, x, y, pixel);
369 /* calc error */
370 rer = rerr[x] - r*dr;
371 ger = gerr[x] - g*dg;
372 ber = berr[x] - b*db;
374 /* distribute error */
375 r = (rer*3)/8;
376 g = (ger*3)/8;
377 b = (ber*3)/8;
378 /* x+1, y */
379 rerr[x+1]+=r;
380 gerr[x+1]+=g;
381 berr[x+1]+=b;
382 /* x, y+1 */
383 nrerr[x]+=r;
384 ngerr[x]+=g;
385 nberr[x]+=b;
386 /* x+1, y+1 */
387 nrerr[x+1]+=rer-2*r;
388 ngerr[x+1]+=ger-2*g;
389 nberr[x+1]+=ber-2*b;
391 ofs+=image->width;
392 /* skip to next line */
393 terr = rerr;
394 rerr = nrerr;
395 nrerr = terr;
397 terr = gerr;
398 gerr = ngerr;
399 ngerr = terr;
401 terr = berr;
402 berr = nberr;
403 nberr = terr;
406 return ximg;
412 static RXImage*
413 image2PseudoColor(RContext *ctx, RImage *image)
415 RXImage *ximg;
416 register int x, y, r, g, b;
417 unsigned char *red, *grn, *blu;
418 unsigned long pixel;
419 const int cpc=ctx->attribs->colors_per_channel;
420 const unsigned short rmask = cpc-1; /* different sizes could be used */
421 const unsigned short gmask = rmask; /* for r,g,b */
422 const unsigned short bmask = rmask;
423 unsigned short *rtable, *gtable, *btable;
424 const int cpccpc = cpc*cpc;
425 unsigned char *data;
426 int ofs;
427 /*register unsigned char maxrgb = 0xff;*/
429 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
430 if (!ximg) {
431 return NULL;
434 red = image->data[0];
435 grn = image->data[1];
436 blu = image->data[2];
438 data = (unsigned char *)ximg->image->data;
440 /* Tables are same at the moment because rmask==gmask==bmask. */
441 rtable = computeTable(rmask);
442 gtable = computeTable(gmask);
443 btable = computeTable(bmask);
445 if (rtable==NULL || gtable==NULL || btable==NULL) {
446 RErrorCode = RERR_NOMEMORY;
447 RDestroyXImage(ctx, ximg);
448 return NULL;
451 if (ctx->attribs->render_mode == RBestMatchRendering) {
452 /* fake match */
453 #ifdef DEBUG
454 printf("pseudo color match with %d colors per channel\n", cpc);
455 #endif
456 for (y=0, ofs = 0; y<image->height; y++) {
457 for (x=0; x<image->width; x++, ofs++) {
458 /* reduce pixel */
459 r = rtable[red[ofs]];
460 g = gtable[grn[ofs]];
461 b = btable[blu[ofs]];
462 pixel = r*cpccpc + g*cpc + b;
463 /*data[ofs] = ctx->colors[pixel].pixel;*/
464 XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
467 } else {
468 /* dither */
469 short *rerr, *gerr, *berr;
470 short *nrerr, *ngerr, *nberr;
471 short *terr;
472 int rer, ger, ber;
473 const int dr=0xff/rmask;
474 const int dg=0xff/gmask;
475 const int db=0xff/bmask;
477 #ifdef DEBUG
478 printf("pseudo color dithering with %d colors per channel\n", cpc);
479 #endif
480 rerr = (short*)alloca((image->width+2)*sizeof(short));
481 gerr = (short*)alloca((image->width+2)*sizeof(short));
482 berr = (short*)alloca((image->width+2)*sizeof(short));
483 nrerr = (short*)alloca((image->width+2)*sizeof(short));
484 ngerr = (short*)alloca((image->width+2)*sizeof(short));
485 nberr = (short*)alloca((image->width+2)*sizeof(short));
486 if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
487 RErrorCode = RERR_NOMEMORY;
488 RDestroyXImage(ctx, ximg);
489 return NULL;
491 for (x=0; x<image->width; x++) {
492 rerr[x] = red[x];
493 gerr[x] = grn[x];
494 berr[x] = blu[x];
496 rerr[x] = gerr[x] = berr[x] = 0;
497 /* convert and dither the image to XImage */
498 for (y=0, ofs=0; y<image->height; y++) {
499 if (y<image->height-1) {
500 int x1;
501 for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
502 nrerr[x] = red[x1];
503 ngerr[x] = grn[x1];
504 nberr[x] = blu[x1];
506 /* last column */
507 x1--;
508 nrerr[x] = red[x1];
509 ngerr[x] = grn[x1];
510 nberr[x] = blu[x1];
512 for (x=0; x<image->width; x++, ofs++) {
513 /* reduce pixel */
514 if (rerr[x]>0xff) rerr[x]=0xff; else if (rerr[x]<0) rerr[x]=0;
515 if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
516 if (berr[x]>0xff) berr[x]=0xff; else if (berr[x]<0) berr[x]=0;
518 r = rtable[rerr[x]];
519 g = gtable[gerr[x]];
520 b = btable[berr[x]];
522 pixel = r*cpccpc + g*cpc + b;
523 /*data[ofs] = ctx->colors[pixel].pixel;*/
524 XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
526 /* calc error */
527 rer = rerr[x] - r*dr;
528 ger = gerr[x] - g*dg;
529 ber = berr[x] - b*db;
531 /* distribute error */
532 rerr[x+1]+=(rer*7)/16;
533 gerr[x+1]+=(ger*7)/16;
534 berr[x+1]+=(ber*7)/16;
536 nrerr[x]+=(rer*5)/16;
537 ngerr[x]+=(ger*5)/16;
538 nberr[x]+=(ber*5)/16;
540 if (x>0) {
541 nrerr[x-1]+=(rer*3)/16;
542 ngerr[x-1]+=(ger*3)/16;
543 nberr[x-1]+=(ber*3)/16;
546 nrerr[x+1]+=rer/16;
547 ngerr[x+1]+=ger/16;
548 nberr[x+1]+=ber/16;
549 #if 0
550 /* distribute error */
551 r = (rer*3)/8;
552 g = (ger*3)/8;
553 b = (ber*3)/8;
554 /* x+1, y */
555 rerr[x+1]+=r;
556 gerr[x+1]+=g;
557 berr[x+1]+=b;
558 /* x, y+1 */
559 nrerr[x]+=r;
560 ngerr[x]+=g;
561 nberr[x]+=b;
562 /* x+1, y+1 */
563 nrerr[x+1]+=rer-2*r;
564 ngerr[x+1]+=ger-2*g;
565 nberr[x+1]+=ber-2*b;
566 #endif
568 /* skip to next line */
569 terr = rerr;
570 rerr = nrerr;
571 nrerr = terr;
573 terr = gerr;
574 gerr = ngerr;
575 ngerr = terr;
577 terr = berr;
578 berr = nberr;
579 nberr = terr;
582 ximg->image->data = (char*)data;
584 return ximg;
588 static RXImage*
589 image2GrayScale(RContext *ctx, RImage *image)
591 RXImage *ximg;
592 register int x, y, g;
593 unsigned char *red, *grn, *blu;
594 const int cpc=ctx->attribs->colors_per_channel;
595 unsigned short gmask;
596 unsigned short *table;
597 unsigned char *data;
598 int ofs;
599 /*register unsigned char maxrgb = 0xff;*/
601 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
602 if (!ximg) {
603 return NULL;
606 red = image->data[0];
607 grn = image->data[1];
608 blu = image->data[2];
610 data = (unsigned char *)ximg->image->data;
612 if (ctx->vclass == StaticGray)
613 gmask = (1<<ctx->depth) - 1; /* use all grays */
614 else
615 gmask = cpc*cpc*cpc-1;
617 table = computeTable(gmask);
619 if (table==NULL) {
620 RErrorCode = RERR_NOMEMORY;
621 RDestroyXImage(ctx, ximg);
622 return NULL;
625 if (ctx->attribs->render_mode == RBestMatchRendering) {
626 /* fake match */
627 #ifdef DEBUG
628 printf("grayscale match with %d colors per channel\n", cpc);
629 #endif
630 for (y=0, ofs = 0; y<image->height; y++) {
631 for (x=0; x<image->width; x++, ofs++) {
632 /* reduce pixel */
633 g = table[(red[ofs]*30+grn[ofs]*59+blu[ofs]*11)/100];
635 /*data[ofs] = ctx->colors[g].pixel;*/
636 XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
639 } else {
640 /* dither */
641 short *gerr;
642 short *ngerr;
643 short *terr;
644 int ger;
645 const int dg=0xff/gmask;
647 #ifdef DEBUG
648 printf("grayscale dither with %d colors per channel\n", cpc);
649 #endif
650 gerr = (short*)alloca((image->width+2)*sizeof(short));
651 ngerr = (short*)alloca((image->width+2)*sizeof(short));
652 if (!gerr || !ngerr) {
653 RErrorCode = RERR_NOMEMORY;
654 RDestroyXImage(ctx, ximg);
655 return NULL;
657 for (x=0; x<image->width; x++) {
658 gerr[x] = (red[x]*30 + grn[x]*59 + blu[x]*11)/100;
660 gerr[x] = 0;
661 /* convert and dither the image to XImage */
662 for (y=0, ofs=0; y<image->height; y++) {
663 if (y<image->height-1) {
664 int x1;
665 for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
666 ngerr[x] = (red[x1]*30 + grn[x1]*59 + blu[x1]*11)/100;
668 /* last column */
669 x1--;
670 ngerr[x] = (red[x1]*30 + grn[x1]*59 + blu[x1]*11)/100;
672 for (x=0; x<image->width; x++, ofs++) {
673 /* reduce pixel */
674 if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
676 g = table[gerr[x]];
678 /*data[ofs] = ctx->colors[g].pixel;*/
679 XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
680 /* calc error */
681 ger = gerr[x] - g*dg;
683 /* distribute error */
684 g = (ger*3)/8;
685 /* x+1, y */
686 gerr[x+1]+=g;
687 /* x, y+1 */
688 ngerr[x]+=g;
689 /* x+1, y+1 */
690 ngerr[x+1]+=ger-2*g;
692 /* skip to next line */
693 terr = gerr;
694 gerr = ngerr;
695 ngerr = terr;
698 ximg->image->data = (char*)data;
700 return ximg;
704 static RXImage*
705 image2Bitmap(RContext *ctx, RImage *image, int threshold)
707 RXImage *ximg;
708 unsigned char *alpha;
709 int x, y;
711 ximg = RCreateXImage(ctx, 1, image->width, image->height);
712 if (!ximg) {
713 return NULL;
715 alpha = image->data[3];
717 for (y = 0; y < image->height; y++) {
718 for (x = 0; x < image->width; x++) {
719 XPutPixel(ximg->image, x, y, (*alpha <= threshold ? 0 : 1));
720 alpha++;
724 return ximg;
729 int
730 RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
732 RXImage *ximg=NULL;
733 #ifdef XSHM
734 Pixmap tmp;
735 #endif
737 assert(context!=NULL);
738 assert(image!=NULL);
739 assert(pixmap!=NULL);
741 /* clear error message */
742 if (context->vclass == TrueColor) {
744 if (context->attribs->render_mode == RDitheredRendering
745 && (context->depth == 15 || context->depth == 16))
746 ximg = image2TrueColorD16(context, image);
747 else
748 ximg = image2TrueColor(context, image);
750 } else if (context->vclass == PseudoColor || context->vclass == StaticColor)
751 ximg = image2PseudoColor(context, image);
752 else if (context->vclass == GrayScale || context->vclass == StaticGray)
753 ximg = image2GrayScale(context, image);
755 if (!ximg) {
756 #ifdef C_ALLOCA
757 alloca(0);
758 #endif
759 return False;
763 *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
764 image->height, context->depth);
766 #ifdef XSHM
767 if (context->flags.use_shared_pixmap && ximg->is_shared)
768 tmp = R_CreateXImageMappedPixmap(context, ximg);
769 else
770 tmp = None;
771 if (tmp) {
773 * We have to copy the shm Pixmap into a normal Pixmap because
774 * otherwise, we would have to control when Pixmaps are freed so
775 * that we can detach their shm segments. This is a problem if the
776 * program crash, leaving stale shared memory segments in the
777 * system (lots of them). But with some work, we can optimize
778 * things and remove this XCopyArea. This will require
779 * explicitly freeing all pixmaps when exiting or restarting
780 * wmaker.
782 XCopyArea(context->dpy, tmp, *pixmap, context->copy_gc, 0, 0,
783 image->width, image->height, 0, 0);
784 XFreePixmap(context->dpy, tmp);
785 } else {
786 RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
787 image->width, image->height);
789 #else /* !XSHM */
790 RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
791 image->width, image->height);
792 #endif /* !XSHM */
794 RDestroyXImage(context, ximg);
796 #ifdef C_ALLOCA
797 alloca(0);
798 #endif
799 return True;
803 int
804 RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
805 Pixmap *mask, int threshold)
807 GC gc;
808 XGCValues gcv;
809 RXImage *ximg=NULL;
811 assert(context!=NULL);
812 assert(image!=NULL);
813 assert(pixmap!=NULL);
814 assert(mask!=NULL);
816 if (!RConvertImage(context, image, pixmap))
817 return False;
819 if (image->data[3]==NULL) {
820 *mask = None;
821 return True;
824 ximg = image2Bitmap(context, image, threshold);
826 if (!ximg) {
827 #ifdef C_ALLOCA
828 alloca(0);
829 #endif
830 return False;
832 *mask = XCreatePixmap(context->dpy, context->drawable, image->width,
833 image->height, 1);
834 gcv.foreground = context->black;
835 gcv.background = context->white;
836 gcv.graphics_exposures = False;
837 gc = XCreateGC(context->dpy, *mask, GCForeground|GCBackground
838 |GCGraphicsExposures, &gcv);
839 RPutXImage(context, *mask, gc, ximg, 0, 0, 0, 0,
840 image->width, image->height);
841 RDestroyXImage(context, ximg);
843 #ifdef C_ALLOCA
844 alloca(0);
845 #endif
846 return True;
850 Bool
851 RGetClosestXColor(RContext *context, RColor *color, XColor *retColor)
853 if (context->vclass == TrueColor) {
854 unsigned short rmask, gmask, bmask;
855 unsigned short roffs, goffs, boffs;
856 unsigned short *rtable, *gtable, *btable;
858 roffs = context->red_offset;
859 goffs = context->green_offset;
860 boffs = context->blue_offset;
862 rmask = context->visual->red_mask >> roffs;
863 gmask = context->visual->green_mask >> goffs;
864 bmask = context->visual->blue_mask >> boffs;
866 rtable = computeTable(rmask);
867 gtable = computeTable(gmask);
868 btable = computeTable(bmask);
870 retColor->pixel = (rtable[color->red]<<roffs) |
871 (gtable[color->green]<<goffs) | (btable[color->blue]<<boffs);
873 retColor->red = color->red << 8;
874 retColor->green = color->green << 8;
875 retColor->blue = color->blue << 8;
876 retColor->flags = DoRed|DoGreen|DoBlue;
878 } else if (context->vclass == PseudoColor || context->vclass == StaticColor) {
879 const int cpc=context->attribs->colors_per_channel;
880 const unsigned short rmask = cpc-1; /* different sizes could be used */
881 const unsigned short gmask = rmask; /* for r,g,b */
882 const unsigned short bmask = rmask;
883 unsigned short *rtable, *gtable, *btable;
884 const int cpccpc = cpc*cpc;
885 int index;
887 rtable = computeTable(rmask);
888 gtable = computeTable(gmask);
889 btable = computeTable(bmask);
891 if (rtable==NULL || gtable==NULL || btable==NULL) {
892 RErrorCode = RERR_NOMEMORY;
893 return False;
895 index = rtable[color->red]*cpccpc + gtable[color->green]*cpc
896 + btable[color->blue];
897 *retColor = context->colors[index];
898 } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
900 const int cpc = context->attribs->colors_per_channel;
901 unsigned short gmask;
902 unsigned short *table;
903 int index;
905 if (context->vclass == StaticGray)
906 gmask = (1<<context->depth) - 1; /* use all grays */
907 else
908 gmask = cpc*cpc*cpc-1;
910 table = computeTable(gmask);
911 if (!table)
912 return False;
914 index = table[(color->red*30 + color->green*59 + color->blue*11)/100];
916 *retColor = context->colors[index];
917 } else {
918 RErrorCode = RERR_INTERNAL;
919 return False;
922 return True;