1 /*
2 * Copyright (C) 1989-95 GROUPE BULL
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * Except as contained in this notice, the name of GROUPE BULL shall not be
22 * used in advertising or otherwise to promote the sale, use or other dealings
23 * in this Software without prior written authorization from GROUPE BULL.
24 */
25
26 /*****************************************************************************\
27 * create.c: *
28 * *
29 * XPM library *
30 * Create an X image and possibly its related shape mask *
31 * from the given XpmImage. *
32 * *
33 * Developed by Arnaud Le Hors *
34 \*****************************************************************************/
35
36 /*
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
39 */
40
41 /*
42 * The code related to AMIGA has been added by
43 * Lorens Younes (d93-hyo@nada.kth.se) 4/96
44 */
45
46 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51 #include "XpmI.h"
52 #include <ctype.h>
53
54 LFUNC(xpmVisualType, int, (Visual *visual));
55
56 LFUNC(AllocColor, int, (Display *display, Colormap colormap,
57 char *colorname, XColor *xcolor, void *closure));
58 LFUNC(FreeColors, int, (Display *display, Colormap colormap,
59 Pixel *pixels, int n, void *closure));
60
61 #ifndef FOR_MSW
62 LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
63 Visual *visual, XColor *col,
64 Pixel *image_pixel, Pixel *mask_pixel,
65 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
66 XpmAttributes *attributes, XColor *cols, int ncols,
67 XpmAllocColorFunc allocColor, void *closure));
68 #else
69 /* let the window system take care of close colors */
70 #endif
71
72 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
73 char *colorname, unsigned int color_index,
74 Pixel *image_pixel, Pixel *mask_pixel,
75 unsigned int *mask_pixel_index,
76 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
77 Pixel *used_pixels, unsigned int *nused_pixels,
78 XpmAttributes *attributes, XColor *cols, int ncols,
79 XpmAllocColorFunc allocColor, void *closure));
80
81 LFUNC(CreateXImage, int, (Display *display, Visual *visual,
82 unsigned int depth, int format, unsigned int width,
83 unsigned int height, XImage **image_return));
84
85 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
86 XpmColor *colors, unsigned int ncolors,
87 Pixel *image_pixels, Pixel *mask_pixels,
88 unsigned int *mask_pixel_index,
89 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
90 Pixel *used_pixels, unsigned int *nused_pixels));
91
92 #ifndef FOR_MSW
93 LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
94 unsigned int height, unsigned int ncolors,
95 unsigned int cpp, XpmColor *colorTable,
96 xpmHashTable *hashtable,
97 XImage *image, Pixel *image_pixels,
98 XImage *mask, Pixel *mask_pixels));
99 #else /* FOR_MSW */
100 LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
101 unsigned int height, unsigned int ncolors,
102 unsigned int cpp, XpmColor *colorTable,
103 xpmHashTable *hashtable,
104 XImage *image, Pixel *image_pixels,
105 XImage *mask, Pixel *mask_pixels));
106 #endif
107
108 #ifndef FOR_MSW
109 # ifndef AMIGA
110 /* XImage pixel routines */
111 LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
112 unsigned int height, unsigned int *pixelindex,
113 Pixel *pixels));
114
115 LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
116 unsigned int height, unsigned int *pixelindex,
117 Pixel *pixels));
118
119 LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
120 unsigned int height, unsigned int *pixelindex,
121 Pixel *pixels));
122
123 LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
124 unsigned int height, unsigned int *pixelindex,
125 Pixel *pixels));
126
127 LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
128 unsigned int height, unsigned int *pixelindex,
129 Pixel *pixels));
130
131 LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
132 LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
133 #if !defined(WORD64) && !defined(LONG64)
134 LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
135 #endif
136 LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
137 LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
138 LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
139 LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
140 LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
141 LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
142 LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
143
144 # else /* AMIGA */
145 LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width,
146 unsigned int height, unsigned int *pixelindex,
147 Pixel *pixels));
148 # endif/* AMIGA */
149 #else /* FOR_MSW */
150 /* FOR_MSW pixel routine */
151 LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
152 unsigned int width, unsigned int height,
153 unsigned int *pixelindex, Pixel *pixels));
154 #endif /* FOR_MSW */
155
156 #ifdef NEED_STRCASECMP
157 FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
158
159 /*
160 * in case strcasecmp is not provided by the system here is one
161 * which does the trick
162 */
163 int
xpmstrcasecmp(register char * s1,register char * s2)164 xpmstrcasecmp(
165 register char *s1,
166 register char *s2)
167 {
168 register int c1, c2;
169
170 while (*s1 && *s2) {
171 c1 = tolower(*s1);
172 c2 = tolower(*s2);
173 if (c1 != c2)
174 return (c1 - c2);
175 s1++;
176 s2++;
177 }
178 return (int) (*s1 - *s2);
179 }
180
181 #endif
182
183 /*
184 * return the default color key related to the given visual
185 */
186 static int
xpmVisualType(Visual * visual)187 xpmVisualType(Visual *visual)
188 {
189 #ifndef FOR_MSW
190 # ifndef AMIGA
191 switch (visual->class) {
192 case StaticGray:
193 case GrayScale:
194 switch (visual->map_entries) {
195 case 2:
196 return (XPM_MONO);
197 case 4:
198 return (XPM_GRAY4);
199 default:
200 return (XPM_GRAY);
201 }
202 default:
203 return (XPM_COLOR);
204 }
205 # else
206 /* set the key explicitly in the XpmAttributes to override this */
207 return (XPM_COLOR);
208 # endif
209 #else
210 /* there should be a similar switch for MSW */
211 return (XPM_COLOR);
212 #endif
213 }
214
215
216 typedef struct {
217 int cols_index;
218 long closeness;
219 } CloseColor;
220
221 static int
closeness_cmp(const void * a,const void * b)222 closeness_cmp(const void *a, const void *b)
223 {
224 const CloseColor *x = (const CloseColor *) a, *y = (const CloseColor *) b;
225
226 /* cast to int as qsort requires */
227 return (int) (x->closeness - y->closeness);
228 }
229
230
231 /* default AllocColor function:
232 * call XParseColor if colorname is given, return negative value if failure
233 * call XAllocColor and return 0 if failure, positive otherwise
234 */
235 static int
AllocColor(Display * display,Colormap colormap,char * colorname,XColor * xcolor,void * closure)236 AllocColor(
237 Display *display,
238 Colormap colormap,
239 char *colorname,
240 XColor *xcolor,
241 void *closure) /* not used */
242 {
243 int status;
244 if (colorname)
245 if (!XParseColor(display, colormap, colorname, xcolor))
246 return -1;
247 status = XAllocColor(display, colormap, xcolor);
248 return status != 0 ? 1 : 0;
249 }
250
251
252 #ifndef FOR_MSW
253 /*
254 * set a close color in case the exact one can't be set
255 * return 0 if success, 1 otherwise.
256 */
257
258 static int
SetCloseColor(Display * display,Colormap colormap,Visual * visual,XColor * col,Pixel * image_pixel,Pixel * mask_pixel,Pixel * alloc_pixels,unsigned int * nalloc_pixels,XpmAttributes * attributes,XColor * cols,int ncols,XpmAllocColorFunc allocColor,void * closure)259 SetCloseColor(
260 Display *display,
261 Colormap colormap,
262 Visual *visual,
263 XColor *col,
264 Pixel *image_pixel,
265 Pixel *mask_pixel,
266 Pixel *alloc_pixels,
267 unsigned int *nalloc_pixels,
268 XpmAttributes *attributes,
269 XColor *cols,
270 int ncols,
271 XpmAllocColorFunc allocColor,
272 void *closure)
273 {
274
275 /*
276 * Allocation failed, so try close colors. To get here the visual must
277 * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
278 * What about sharing systems like QDSS?). Beware: we have to treat
279 * DirectColor differently.
280 */
281
282
283 long int red_closeness, green_closeness, blue_closeness;
284 int n;
285 Bool alloc_color;
286
287 if (attributes && (attributes->valuemask & XpmCloseness))
288 red_closeness = green_closeness = blue_closeness =
289 attributes->closeness;
290 else {
291 red_closeness = attributes->red_closeness;
292 green_closeness = attributes->green_closeness;
293 blue_closeness = attributes->blue_closeness;
294 }
295 if (attributes && (attributes->valuemask & XpmAllocCloseColors))
296 alloc_color = attributes->alloc_close_colors;
297 else
298 alloc_color = True;
299
300 /*
301 * We sort the colormap by closeness and try to allocate the color
302 * closest to the target. If the allocation of this close color fails,
303 * which almost never happens, then one of two scenarios is possible.
304 * Either the colormap must have changed (since the last close color
305 * allocation or possibly while we were sorting the colormap), or the
306 * color is allocated as Read/Write by some other client. (Note: X
307 * _should_ allow clients to check if a particular color is Read/Write,
308 * but it doesn't! :-( ). We cannot determine which of these scenarios
309 * occurred, so we try the next closest color, and so on, until no more
310 * colors are within closeness of the target. If we knew that the
311 * colormap had changed, we could skip this sequence.
312 *
313 * If _none_ of the colors within closeness of the target can be allocated,
314 * then we can finally be pretty sure that the colormap has actually
315 * changed. In this case we try to allocate the original color (again),
316 * then try the closecolor stuff (again)...
317 *
318 * In theory it would be possible for an infinite loop to occur if another
319 * process kept changing the colormap every time we sorted it, so we set
320 * a maximum on the number of iterations. After this many tries, we use
321 * XGrabServer() to ensure that the colormap remains unchanged.
322 *
323 * This approach gives particularly bad worst case performance - as many as
324 * <MaximumIterations> colormap reads and sorts may be needed, and as
325 * many as <MaximumIterations> * <ColormapSize> attempted allocations
326 * may fail. On an 8-bit system, this means as many as 3 colormap reads,
327 * 3 sorts and 768 failed allocations per execution of this code!
328 * Luckily, my experiments show that in general use in a typical 8-bit
329 * color environment only about 1 in every 10000 allocations fails to
330 * succeed in the fastest possible time. So virtually every time what
331 * actually happens is a single sort followed by a successful allocate.
332 * The very first allocation also costs a colormap read, but no further
333 * reads are usually necessary.
334 */
335
336 #define ITERATIONS 2 /* more than one is almost never
337 * necessary */
338
339 for (n = 0; n <= ITERATIONS; ++n) {
340 CloseColor *closenesses =
341 (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
342 int i, c;
343
344 for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */
345 #define COLOR_FACTOR 3
346 #define BRIGHTNESS_FACTOR 1
347
348 closenesses[i].cols_index = i;
349 closenesses[i].closeness =
350 COLOR_FACTOR * (labs((long) col->red - (long) cols[i].red)
351 + labs((long) col->green - (long) cols[i].green)
352 + labs((long) col->blue - (long) cols[i].blue))
353 + BRIGHTNESS_FACTOR * labs(((long) col->red +
354 (long) col->green +
355 (long) col->blue)
356 - ((long) cols[i].red +
357 (long) cols[i].green +
358 (long) cols[i].blue));
359 }
360 qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
361
362 i = 0;
363 c = closenesses[i].cols_index;
364 while ((long) cols[c].red >= (long) col->red - red_closeness &&
365 (long) cols[c].red <= (long) col->red + red_closeness &&
366 (long) cols[c].green >= (long) col->green - green_closeness &&
367 (long) cols[c].green <= (long) col->green + green_closeness &&
368 (long) cols[c].blue >= (long) col->blue - blue_closeness &&
369 (long) cols[c].blue <= (long) col->blue + blue_closeness) {
370 if (alloc_color) {
371 if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
372 if (n == ITERATIONS)
373 XUngrabServer(display);
374 XpmFree(closenesses);
375 *image_pixel = cols[c].pixel;
376 *mask_pixel = 1;
377 alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
378 return (0);
379 } else {
380 ++i;
381 if (i == ncols)
382 break;
383 c = closenesses[i].cols_index;
384 }
385 } else {
386 if (n == ITERATIONS)
387 XUngrabServer(display);
388 XpmFree(closenesses);
389 *image_pixel = cols[c].pixel;
390 *mask_pixel = 1;
391 return (0);
392 }
393 }
394
395 /* Couldn't allocate _any_ of the close colors! */
396
397 if (n == ITERATIONS)
398 XUngrabServer(display);
399 XpmFree(closenesses);
400
401 if (i == 0 || i == ncols) /* no color close enough or cannot */
402 return (1); /* alloc any color (full of r/w's) */
403
404 if ((*allocColor)(display, colormap, NULL, col, closure)) {
405 *image_pixel = col->pixel;
406 *mask_pixel = 1;
407 alloc_pixels[(*nalloc_pixels)++] = col->pixel;
408 return (0);
409 } else { /* colormap has probably changed, so
410 * re-read... */
411 if (n == ITERATIONS - 1)
412 XGrabServer(display);
413
414 #if 0
415 if (visual->class == DirectColor) {
416 /* TODO */
417 } else
418 #endif
419 XQueryColors(display, colormap, cols, ncols);
420 }
421 }
422 return (1);
423 }
424
425 #define USE_CLOSECOLOR attributes && \
426 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
427 || ((attributes->valuemask & XpmRGBCloseness) && \
428 (attributes->red_closeness != 0 \
429 || attributes->green_closeness != 0 \
430 || attributes->blue_closeness != 0)))
431
432 #else
433 /* FOR_MSW part */
434 /* nothing to do here, the window system does it */
435 #endif
436
437 /*
438 * set the color pixel related to the given colorname,
439 * return 0 if success, 1 otherwise.
440 */
441
442 static int
SetColor(Display * display,Colormap colormap,Visual * visual,char * colorname,unsigned int color_index,Pixel * image_pixel,Pixel * mask_pixel,unsigned int * mask_pixel_index,Pixel * alloc_pixels,unsigned int * nalloc_pixels,Pixel * used_pixels,unsigned int * nused_pixels,XpmAttributes * attributes,XColor * cols,int ncols,XpmAllocColorFunc allocColor,void * closure)443 SetColor(
444 Display *display,
445 Colormap colormap,
446 Visual *visual,
447 char *colorname,
448 unsigned int color_index,
449 Pixel *image_pixel,
450 Pixel *mask_pixel,
451 unsigned int *mask_pixel_index,
452 Pixel *alloc_pixels,
453 unsigned int *nalloc_pixels,
454 Pixel *used_pixels,
455 unsigned int *nused_pixels,
456 XpmAttributes *attributes,
457 XColor *cols,
458 int ncols,
459 XpmAllocColorFunc allocColor,
460 void *closure)
461 {
462 XColor xcolor;
463 int status;
464
465 if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
466 status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
467 if (status < 0) /* parse color failed */
468 return (1);
469
470 if (status == 0) {
471 #ifndef FOR_MSW
472 if (USE_CLOSECOLOR)
473 return (SetCloseColor(display, colormap, visual, &xcolor,
474 image_pixel, mask_pixel,
475 alloc_pixels, nalloc_pixels,
476 attributes, cols, ncols,
477 allocColor, closure));
478 else
479 #endif /* ndef FOR_MSW */
480 return (1);
481 } else
482 alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
483 *image_pixel = xcolor.pixel;
484 #ifndef FOR_MSW
485 *mask_pixel = 1;
486 #else
487 *mask_pixel = RGB(0,0,0);
488 #endif
489 used_pixels[(*nused_pixels)++] = xcolor.pixel;
490 } else {
491 *image_pixel = 0;
492 #ifndef FOR_MSW
493 *mask_pixel = 0;
494 #else
495 *mask_pixel = RGB(255,255,255);
496 #endif
497 /* store the color table index */
498 *mask_pixel_index = color_index;
499 }
500 return (0);
501 }
502
503
504 static int
CreateColors(Display * display,XpmAttributes * attributes,XpmColor * colors,unsigned int ncolors,Pixel * image_pixels,Pixel * mask_pixels,unsigned int * mask_pixel_index,Pixel * alloc_pixels,unsigned int * nalloc_pixels,Pixel * used_pixels,unsigned int * nused_pixels)505 CreateColors(
506 Display *display,
507 XpmAttributes *attributes,
508 XpmColor *colors,
509 unsigned int ncolors,
510 Pixel *image_pixels,
511 Pixel *mask_pixels,
512 unsigned int *mask_pixel_index,
513 Pixel *alloc_pixels,
514 unsigned int *nalloc_pixels,
515 Pixel *used_pixels,
516 unsigned int *nused_pixels)
517 {
518 /* variables stored in the XpmAttributes structure */
519 Visual *visual;
520 Colormap colormap;
521 XpmColorSymbol *colorsymbols = NULL;
522 unsigned int numsymbols;
523 XpmAllocColorFunc allocColor;
524 void *closure;
525
526 char *colorname;
527 unsigned int color, key;
528 Bool pixel_defined;
529 XpmColorSymbol *symbol = NULL;
530 char **defaults;
531 int ErrorStatus = XpmSuccess;
532 char *s;
533 int default_index;
534
535 XColor *cols = NULL;
536 unsigned int ncols = 0;
537
538 /*
539 * retrieve information from the XpmAttributes
540 */
541 if (attributes && attributes->valuemask & XpmColorSymbols) {
542 colorsymbols = attributes->colorsymbols;
543 numsymbols = attributes->numsymbols;
544 } else
545 numsymbols = 0;
546
547 if (attributes && attributes->valuemask & XpmVisual)
548 visual = attributes->visual;
549 else
550 visual = XDefaultVisual(display, XDefaultScreen(display));
551
552 if (attributes && (attributes->valuemask & XpmColormap))
553 colormap = attributes->colormap;
554 else
555 colormap = XDefaultColormap(display, XDefaultScreen(display));
556
557 if (attributes && (attributes->valuemask & XpmColorKey))
558 key = attributes->color_key;
559 else
560 key = xpmVisualType(visual);
561
562 if (attributes && (attributes->valuemask & XpmAllocColor))
563 allocColor = attributes->alloc_color;
564 else
565 allocColor = AllocColor;
566 if (attributes && (attributes->valuemask & XpmColorClosure))
567 closure = attributes->color_closure;
568 else
569 closure = NULL;
570
571 #ifndef FOR_MSW
572 if (USE_CLOSECOLOR) {
573 /* originally from SetCloseColor */
574 #if 0
575 if (visual->class == DirectColor) {
576
577 /*
578 * TODO: Implement close colors for DirectColor visuals. This is
579 * difficult situation. Chances are that we will never get here,
580 * because any machine that supports DirectColor will probably
581 * also support TrueColor (and probably PseudoColor). Also,
582 * DirectColor colormaps can be very large, so looking for close
583 * colors may be too slow.
584 */
585 } else {
586 #endif
587 unsigned int i;
588
589 #ifndef AMIGA
590 ncols = visual->map_entries;
591 #else
592 ncols = colormap->Count;
593 #endif
594 cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
595 for (i = 0; i < ncols; ++i)
596 cols[i].pixel = i;
597 XQueryColors(display, colormap, cols, ncols);
598 #if 0
599 }
600 #endif
601 }
602 #endif /* ndef FOR_MSW */
603
604 switch (key) {
605 case XPM_MONO:
606 default_index = 2;
607 break;
608 case XPM_GRAY4:
609 default_index = 3;
610 break;
611 case XPM_GRAY:
612 default_index = 4;
613 break;
614 case XPM_COLOR:
615 default:
616 default_index = 5;
617 break;
618 }
619
620 for (color = 0; color < ncolors; color++, colors++,
621 image_pixels++, mask_pixels++) {
622 colorname = NULL;
623 pixel_defined = False;
624 defaults = (char **) colors;
625
626 /*
627 * look for a defined symbol
628 */
629 if (numsymbols) {
630
631 unsigned int n;
632
633 s = defaults[1];
634 for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
635 if (symbol->name && s && !strcmp(symbol->name, s))
636 /* override name */
637 break;
638 if (!symbol->name && symbol->value) { /* override value */
639 int def_index = default_index;
640
641 while (defaults[def_index] == NULL) /* find defined
642 * colorname */
643 --def_index;
644 if (def_index < 2) {/* nothing towards mono, so try
645 * towards color */
646 def_index = default_index + 1;
647 while (def_index <= 5 && defaults[def_index] == NULL)
648 ++def_index;
649 }
650 if (def_index >= 2 && def_index <= 5 &&
651 defaults[def_index] != NULL &&
652 !xpmstrcasecmp(symbol->value, defaults[def_index]))
653 break;
654 }
655 }
656 if (n != numsymbols) {
657 if (symbol->name && symbol->value)
658 colorname = symbol->value;
659 else
660 pixel_defined = True;
661 }
662 }
663 if (!pixel_defined) { /* pixel not given as symbol value */
664
665 unsigned int k;
666
667 if (colorname) { /* colorname given as symbol value */
668 if (!SetColor(display, colormap, visual, colorname, color,
669 image_pixels, mask_pixels, mask_pixel_index,
670 alloc_pixels, nalloc_pixels, used_pixels,
671 nused_pixels, attributes, cols, ncols,
672 allocColor, closure))
673 pixel_defined = True;
674 else
675 ErrorStatus = XpmColorError;
676 }
677 k = key;
678 while (!pixel_defined && k > 1) {
679 if (defaults[k]) {
680 if (!SetColor(display, colormap, visual, defaults[k],
681 color, image_pixels, mask_pixels,
682 mask_pixel_index, alloc_pixels,
683 nalloc_pixels, used_pixels, nused_pixels,
684 attributes, cols, ncols,
685 allocColor, closure)) {
686 pixel_defined = True;
687 break;
688 } else
689 ErrorStatus = XpmColorError;
690 }
691 k--;
692 }
693 k = key + 1;
694 while (!pixel_defined && k < NKEYS + 1) {
695 if (defaults[k]) {
696 if (!SetColor(display, colormap, visual, defaults[k],
697 color, image_pixels, mask_pixels,
698 mask_pixel_index, alloc_pixels,
699 nalloc_pixels, used_pixels, nused_pixels,
700 attributes, cols, ncols,
701 allocColor, closure)) {
702 pixel_defined = True;
703 break;
704 } else
705 ErrorStatus = XpmColorError;
706 }
707 k++;
708 }
709 if (!pixel_defined) {
710 if (cols)
711 XpmFree(cols);
712 return (XpmColorFailed);
713 }
714 } else {
715 /* simply use the given pixel */
716 *image_pixels = symbol->pixel;
717 /* the following makes the mask to be built even if none
718 is given a particular pixel */
719 if (symbol->value
720 && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
721 *mask_pixels = 0;
722 *mask_pixel_index = color;
723 } else
724 *mask_pixels = 1;
725 used_pixels[(*nused_pixels)++] = *image_pixels;
726 }
727 }
728 if (cols)
729 XpmFree(cols);
730 return (ErrorStatus);
731 }
732
733
734 /* default FreeColors function, simply call XFreeColors */
735 static int
FreeColors(Display * display,Colormap colormap,Pixel * pixels,int n,void * closure)736 FreeColors(
737 Display *display,
738 Colormap colormap,
739 Pixel *pixels,
740 int n,
741 void *closure) /* not used */
742 {
743 return XFreeColors(display, colormap, pixels, n, 0);
744 }
745
746
747 /* function call in case of error */
748
749 #undef RETURN
750 #define RETURN(status) \
751 do \
752 { \
753 ErrorStatus = status; \
754 goto error; \
755 } while(0)
756
757 int
XpmCreateImageFromXpmImage(Display * display,XpmImage * image,XImage ** image_return,XImage ** shapeimage_return,XpmAttributes * attributes)758 XpmCreateImageFromXpmImage(
759 Display *display,
760 XpmImage *image,
761 XImage **image_return,
762 XImage **shapeimage_return,
763 XpmAttributes *attributes)
764 {
765 /* variables stored in the XpmAttributes structure */
766 Visual *visual;
767 Colormap colormap;
768 unsigned int depth;
769 int bitmap_format;
770 XpmFreeColorsFunc freeColors;
771
772 /* variables to return */
773 XImage *ximage = NULL;
774 XImage *shapeimage = NULL;
775 unsigned int mask_pixel_index = XpmUndefPixel;
776 int ErrorStatus;
777
778 /* calculation variables */
779 Pixel *image_pixels = NULL;
780 Pixel *mask_pixels = NULL;
781 Pixel *alloc_pixels = NULL;
782 Pixel *used_pixels = NULL;
783 unsigned int nalloc_pixels = 0;
784 unsigned int nused_pixels = 0;
785
786 /* initialize return values */
787 if (image_return)
788 *image_return = NULL;
789 if (shapeimage_return)
790 *shapeimage_return = NULL;
791
792 /* retrieve information from the XpmAttributes */
793 if (attributes && (attributes->valuemask & XpmVisual))
794 visual = attributes->visual;
795 else
796 visual = XDefaultVisual(display, XDefaultScreen(display));
797
798 if (attributes && (attributes->valuemask & XpmColormap))
799 colormap = attributes->colormap;
800 else
801 colormap = XDefaultColormap(display, XDefaultScreen(display));
802
803 if (attributes && (attributes->valuemask & XpmDepth))
804 depth = attributes->depth;
805 else
806 depth = XDefaultDepth(display, XDefaultScreen(display));
807
808 if (attributes && (attributes->valuemask & XpmBitmapFormat))
809 bitmap_format = attributes->bitmap_format;
810 else
811 bitmap_format = ZPixmap;
812
813 if (attributes && (attributes->valuemask & XpmFreeColors))
814 freeColors = attributes->free_colors;
815 else
816 freeColors = FreeColors;
817
818 ErrorStatus = XpmSuccess;
819
820 if (image->ncolors >= UINT_MAX / sizeof(Pixel))
821 return (XpmNoMemory);
822
823 /* malloc pixels index tables */
824 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
825 if (!image_pixels)
826 return (XpmNoMemory);
827
828 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
829 if (!mask_pixels)
830 RETURN(XpmNoMemory);
831
832 /* maximum of allocated pixels will be the number of colors */
833 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
834 if (!alloc_pixels)
835 RETURN(XpmNoMemory);
836
837 /* maximum of allocated pixels will be the number of colors */
838 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
839 if (!used_pixels)
840 RETURN(XpmNoMemory);
841
842 /* get pixel colors, store them in index tables */
843 ErrorStatus = CreateColors(display, attributes, image->colorTable,
844 image->ncolors, image_pixels, mask_pixels,
845 &mask_pixel_index, alloc_pixels, &nalloc_pixels,
846 used_pixels, &nused_pixels);
847
848 if (ErrorStatus != XpmSuccess
849 && (ErrorStatus < 0 || (attributes
850 && (attributes->valuemask & XpmExactColors)
851 && attributes->exactColors)))
852 RETURN(ErrorStatus);
853
854 /* create the ximage */
855 if (image_return) {
856 ErrorStatus = CreateXImage(display, visual, depth,
857 (depth == 1 ? bitmap_format : ZPixmap),
858 image->width, image->height, &ximage);
859 if (ErrorStatus != XpmSuccess)
860 RETURN(ErrorStatus);
861
862 #ifndef FOR_MSW
863 # ifndef AMIGA
864
865 /*
866 * set the ximage data using optimized functions for ZPixmap
867 */
868
869 if (ximage->bits_per_pixel == 8)
870 PutImagePixels8(ximage, image->width, image->height,
871 image->data, image_pixels);
872 else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
873 (ximage->byte_order == ximage->bitmap_bit_order))
874 PutImagePixels1(ximage, image->width, image->height,
875 image->data, image_pixels);
876 else if (ximage->bits_per_pixel == 16)
877 PutImagePixels16(ximage, image->width, image->height,
878 image->data, image_pixels);
879 else if (ximage->bits_per_pixel == 32)
880 PutImagePixels32(ximage, image->width, image->height,
881 image->data, image_pixels);
882 else
883 PutImagePixels(ximage, image->width, image->height,
884 image->data, image_pixels);
885 # else /* AMIGA */
886 APutImagePixels(ximage, image->width, image->height,
887 image->data, image_pixels);
888 # endif
889 #else /* FOR_MSW */
890 MSWPutImagePixels(display, ximage, image->width, image->height,
891 image->data, image_pixels);
892 #endif
893 }
894 /* create the shape mask image */
895 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
896 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
897 image->width, image->height, &shapeimage);
898 if (ErrorStatus != XpmSuccess)
899 RETURN(ErrorStatus);
900
901 #ifndef FOR_MSW
902 # ifndef AMIGA
903 PutImagePixels1(shapeimage, image->width, image->height,
904 image->data, mask_pixels);
905 # else /* AMIGA */
906 APutImagePixels(shapeimage, image->width, image->height,
907 image->data, mask_pixels);
908 # endif
909 #else /* FOR_MSW */
910 MSWPutImagePixels(display, shapeimage, image->width, image->height,
911 image->data, mask_pixels);
912 #endif
913
914 }
915 XpmFree(image_pixels);
916 XpmFree(mask_pixels);
917
918 /* if requested return used pixels in the XpmAttributes structure */
919 if (attributes && (attributes->valuemask & XpmReturnPixels ||
920 /* 3.2 backward compatibility code */
921 attributes->valuemask & XpmReturnInfos)) {
922 /* end 3.2 bc */
923 attributes->pixels = used_pixels;
924 attributes->npixels = nused_pixels;
925 attributes->mask_pixel = mask_pixel_index;
926 } else
927 XpmFree(used_pixels);
928
929 /* if requested return alloc'ed pixels in the XpmAttributes structure */
930 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
931 attributes->alloc_pixels = alloc_pixels;
932 attributes->nalloc_pixels = nalloc_pixels;
933 } else
934 XpmFree(alloc_pixels);
935
936 /* return created images */
937 if (image_return)
938 *image_return = ximage;
939 if (shapeimage_return)
940 *shapeimage_return = shapeimage;
941
942 return (ErrorStatus);
943
944 /* exit point in case of error, free only locally allocated variables */
945 error:
946 if (ximage)
947 XDestroyImage(ximage);
948 if (shapeimage)
949 XDestroyImage(shapeimage);
950 if (image_pixels)
951 XpmFree(image_pixels);
952 if (mask_pixels)
953 XpmFree(mask_pixels);
954 if (nalloc_pixels)
955 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
956 if (alloc_pixels)
957 XpmFree(alloc_pixels);
958 if (used_pixels)
959 XpmFree(used_pixels);
960
961 return (ErrorStatus);
962 }
963
964
965 /*
966 * Create an XImage with its data
967 */
968 static int
CreateXImage(Display * display,Visual * visual,unsigned int depth,int format,unsigned int width,unsigned int height,XImage ** image_return)969 CreateXImage(
970 Display *display,
971 Visual *visual,
972 unsigned int depth,
973 int format,
974 unsigned int width,
975 unsigned int height,
976 XImage **image_return)
977 {
978 int bitmap_pad;
979
980 /* first get bitmap_pad */
981 if (depth > 16)
982 bitmap_pad = 32;
983 else if (depth > 8)
984 bitmap_pad = 16;
985 else
986 bitmap_pad = 8;
987
988 /* then create the XImage with data = NULL and bytes_per_line = 0 */
989 *image_return = XCreateImage(display, visual, depth, format, 0, 0,
990 width, height, bitmap_pad, 0);
991 if (!*image_return)
992 return (XpmNoMemory);
993
994 #if !defined(FOR_MSW) && !defined(AMIGA)
995 if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
996 XDestroyImage(*image_return);
997 return XpmNoMemory;
998 }
999 /* now that bytes_per_line must have been set properly alloc data */
1000 if((*image_return)->bytes_per_line == 0 || height == 0)
1001 return XpmNoMemory;
1002 (*image_return)->data =
1003 (char *) XpmMalloc((*image_return)->bytes_per_line * height);
1004
1005 if (!(*image_return)->data) {
1006 XDestroyImage(*image_return);
1007 *image_return = NULL;
1008 return (XpmNoMemory);
1009 }
1010 #else
1011 /* under FOR_MSW and AMIGA XCreateImage has done it all */
1012 #endif
1013 return (XpmSuccess);
1014 }
1015
1016 #ifndef FOR_MSW
1017 # ifndef AMIGA
1018 /*
1019 * The functions below are written from X11R5 MIT's code (XImUtil.c)
1020 *
1021 * The idea is to have faster functions than the standard XPutPixel function
1022 * to build the image data. Indeed we can speed up things by suppressing tests
1023 * performed for each pixel. We do the same tests but at the image level.
1024 * We also assume that we use only ZPixmap images with null offsets.
1025 */
1026
1027 LFUNC(_putbits, void, (register char *src, int dstoffset,
1028 register int numbits, register char *dst));
1029
1030 LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
1031
1032 static unsigned char const _reverse_byte[0x100] = {
1033 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1034 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1035 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1036 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1037 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1038 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1039 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1040 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1041 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1042 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1043 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1044 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1045 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1046 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1047 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1048 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1049 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1050 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1051 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1052 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1053 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1054 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1055 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1056 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1057 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1058 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1059 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1060 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1061 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1062 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1063 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1064 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1065 };
1066
1067 static int
_XReverse_Bytes(register unsigned char * bpt,register unsigned int nb)1068 _XReverse_Bytes(
1069 register unsigned char *bpt,
1070 register unsigned int nb)
1071 {
1072 do {
1073 *bpt = _reverse_byte[*bpt];
1074 bpt++;
1075 } while (--nb > 0); /* is nb user-controled? */
1076 return 0;
1077 }
1078
1079
1080 void
xpm_xynormalizeimagebits(register unsigned char * bp,register XImage * img)1081 xpm_xynormalizeimagebits(
1082 register unsigned char *bp,
1083 register XImage *img)
1084 {
1085 register unsigned char c;
1086
1087 if (img->byte_order != img->bitmap_bit_order) {
1088 switch (img->bitmap_unit) {
1089
1090 case 16:
1091 c = *bp;
1092 *bp = *(bp + 1);
1093 *(bp + 1) = c;
1094 break;
1095
1096 case 32:
1097 c = *(bp + 3);
1098 *(bp + 3) = *bp;
1099 *bp = c;
1100 c = *(bp + 2);
1101 *(bp + 2) = *(bp + 1);
1102 *(bp + 1) = c;
1103 break;
1104 }
1105 }
1106 if (img->bitmap_bit_order == MSBFirst)
1107 _XReverse_Bytes(bp, img->bitmap_unit >> 3);
1108 }
1109
1110 void
xpm_znormalizeimagebits(register unsigned char * bp,register XImage * img)1111 xpm_znormalizeimagebits(
1112 register unsigned char *bp,
1113 register XImage *img)
1114 {
1115 register unsigned char c;
1116
1117 switch (img->bits_per_pixel) {
1118
1119 case 2:
1120 _XReverse_Bytes(bp, 1);
1121 break;
1122
1123 case 4:
1124 *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1125 break;
1126
1127 case 16:
1128 c = *bp;
1129 *bp = *(bp + 1);
1130 *(bp + 1) = c;
1131 break;
1132
1133 case 24:
1134 c = *(bp + 2);
1135 *(bp + 2) = *bp;
1136 *bp = c;
1137 break;
1138
1139 case 32:
1140 c = *(bp + 3);
1141 *(bp + 3) = *bp;
1142 *bp = c;
1143 c = *(bp + 2);
1144 *(bp + 2) = *(bp + 1);
1145 *(bp + 1) = c;
1146 break;
1147 }
1148 }
1149
1150 static unsigned char const _lomask[0x09] = {
1151 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1152 static unsigned char const _himask[0x09] = {
1153 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1154
1155 static void
_putbits(register char * src,int dstoffset,register int numbits,register char * dst)1156 _putbits(
1157 register char *src, /* address of source bit string */
1158 int dstoffset, /* bit offset into destination;
1159 * range is 0-31 */
1160 register int numbits, /* number of bits to copy to
1161 * destination */
1162 register char *dst) /* address of destination bit string */
1163 {
1164 register unsigned char chlo, chhi;
1165 int hibits;
1166
1167 dst = dst + (dstoffset >> 3);
1168 dstoffset = dstoffset & 7;
1169 hibits = 8 - dstoffset;
1170 chlo = *dst & _lomask[dstoffset];
1171 for (;;) {
1172 chhi = (*src << dstoffset) & _himask[dstoffset];
1173 if (numbits <= hibits) {
1174 chhi = chhi & _lomask[dstoffset + numbits];
1175 *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1176 break;
1177 }
1178 *dst = chhi | chlo;
1179 dst++;
1180 numbits = numbits - hibits;
1181 chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1182 src++;
1183 if (numbits <= dstoffset) {
1184 chlo = chlo & _lomask[numbits];
1185 *dst = (*dst & _himask[numbits]) | chlo;
1186 break;
1187 }
1188 numbits = numbits - dstoffset;
1189 }
1190 }
1191
1192 /*
1193 * Default method to write pixels into a Z image data structure.
1194 * The algorithm used is:
1195 *
1196 * copy the destination bitmap_unit or Zpixel to temp
1197 * normalize temp if needed
1198 * copy the pixel bits into the temp
1199 * renormalize temp if needed
1200 * copy the temp back into the destination image data
1201 */
1202
1203 static void
PutImagePixels(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1204 PutImagePixels(
1205 XImage *image,
1206 unsigned int width,
1207 unsigned int height,
1208 unsigned int *pixelindex,
1209 Pixel *pixels)
1210 {
1211 register char *src;
1212 register char *dst;
1213 register unsigned int *iptr;
1214 register unsigned int x, y;
1215 register char *data;
1216 Pixel pixel, px;
1217 int nbytes, depth, ibu, ibpp, i;
1218
1219 data = image->data;
1220 iptr = pixelindex;
1221 depth = image->depth;
1222 if (depth == 1) {
1223 ibu = image->bitmap_unit;
1224 for (y = 0; y < height; y++) /* how can we trust height */
1225 for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1226 pixel = pixels[*iptr];
1227 for (i = 0, px = pixel; i < sizeof(unsigned long);
1228 i++, px >>= 8)
1229 ((unsigned char *) &pixel)[i] = px;
1230 src = &data[XYINDEX(x, y, image)];
1231 dst = (char *) &px;
1232 px = 0;
1233 nbytes = ibu >> 3;
1234 for (i = nbytes; --i >= 0;)
1235 *dst++ = *src++;
1236 XYNORMALIZE(&px, image);
1237 _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1238 XYNORMALIZE(&px, image);
1239 src = (char *) &px;
1240 dst = &data[XYINDEX(x, y, image)];
1241 for (i = nbytes; --i >= 0;)
1242 *dst++ = *src++;
1243 }
1244 } else {
1245 ibpp = image->bits_per_pixel;
1246 for (y = 0; y < height; y++)
1247 for (x = 0; x < width; x++, iptr++) {
1248 pixel = pixels[*iptr];
1249 if (depth == 4)
1250 pixel &= 0xf;
1251 for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1252 px >>= 8)
1253 ((unsigned char *) &pixel)[i] = px;
1254 src = &data[ZINDEX(x, y, image)];
1255 dst = (char *) &px;
1256 px = 0;
1257 nbytes = (ibpp + 7) >> 3;
1258 for (i = nbytes; --i >= 0;)
1259 *dst++ = *src++;
1260 ZNORMALIZE(&px, image);
1261 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1262 ZNORMALIZE(&px, image);
1263 src = (char *) &px;
1264 dst = &data[ZINDEX(x, y, image)];
1265 for (i = nbytes; --i >= 0;)
1266 *dst++ = *src++;
1267 }
1268 }
1269 }
1270
1271 /*
1272 * write pixels into a 32-bits Z image data structure
1273 */
1274
1275 #if !defined(WORD64) && !defined(LONG64)
1276 /* this item is static but deterministic so let it slide; doesn't
1277 * hurt re-entrancy of this library. Note if it is actually const then would
1278 * be OK under rules of ANSI-C but probably not C++ which may not
1279 * want to allocate space for it.
1280 */
1281 static unsigned long byteorderpixel = MSBFirst << 24;
1282
1283 #endif
1284
1285 /*
1286 WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1287 3.2e code - by default you get the speeded-up version.
1288 */
1289
1290 static void
PutImagePixels32(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1291 PutImagePixels32(
1292 XImage *image,
1293 unsigned int width,
1294 unsigned int height,
1295 unsigned int *pixelindex,
1296 Pixel *pixels)
1297 {
1298 unsigned char *data;
1299 unsigned int *iptr;
1300 unsigned int y;
1301 Pixel pixel;
1302
1303 #ifdef WITHOUT_SPEEDUPS
1304
1305 unsigned int x;
1306 unsigned char *addr;
1307
1308 data = (unsigned char *) image->data;
1309 iptr = pixelindex;
1310 #if !defined(WORD64) && !defined(LONG64)
1311 if (*((char *) &byteorderpixel) == image->byte_order) {
1312 for (y = 0; y < height; y++)
1313 for (x = 0; x < width; x++, iptr++) {
1314 addr = &data[ZINDEX32(x, y, image)];
1315 *((unsigned long *) addr) = pixels[*iptr];
1316 }
1317 } else
1318 #endif
1319 if (image->byte_order == MSBFirst)
1320 for (y = 0; y < height; y++)
1321 for (x = 0; x < width; x++, iptr++) {
1322 addr = &data[ZINDEX32(x, y, image)];
1323 pixel = pixels[*iptr];
1324 addr[0] = pixel >> 24;
1325 addr[1] = pixel >> 16;
1326 addr[2] = pixel >> 8;
1327 addr[3] = pixel;
1328 }
1329 else
1330 for (y = 0; y < height; y++)
1331 for (x = 0; x < width; x++, iptr++) {
1332 addr = &data[ZINDEX32(x, y, image)];
1333 pixel = pixels[*iptr];
1334 addr[0] = pixel;
1335 addr[1] = pixel >> 8;
1336 addr[2] = pixel >> 16;
1337 addr[3] = pixel >> 24;
1338 }
1339
1340 #else /* WITHOUT_SPEEDUPS */
1341
1342 unsigned int bpl = image->bytes_per_line;
1343 unsigned char *data_ptr, *max_data;
1344
1345 data = (unsigned char *) image->data;
1346 iptr = pixelindex;
1347 #if !defined(WORD64) && !defined(LONG64)
1348 if (*((char *) &byteorderpixel) == image->byte_order) {
1349 for (y = 0; y < height; y++) {
1350 data_ptr = data;
1351 max_data = data_ptr + (width << 2);
1352
1353 while (data_ptr < max_data) {
1354 *((unsigned long *) data_ptr) = pixels[*(iptr++)];
1355 data_ptr += (1 << 2);
1356 }
1357 data += bpl;
1358 }
1359 } else
1360 #endif
1361 if (image->byte_order == MSBFirst)
1362 for (y = 0; y < height; y++) {
1363 data_ptr = data;
1364 max_data = data_ptr + (width << 2);
1365
1366 while (data_ptr < max_data) {
1367 pixel = pixels[*(iptr++)];
1368
1369 *data_ptr++ = pixel >> 24;
1370 *data_ptr++ = pixel >> 16;
1371 *data_ptr++ = pixel >> 8;
1372 *data_ptr++ = pixel;
1373
1374 }
1375 data += bpl;
1376 }
1377 else
1378 for (y = 0; y < height; y++) {
1379 data_ptr = data;
1380 max_data = data_ptr + (width << 2);
1381
1382 while (data_ptr < max_data) {
1383 pixel = pixels[*(iptr++)];
1384
1385 *data_ptr++ = pixel;
1386 *data_ptr++ = pixel >> 8;
1387 *data_ptr++ = pixel >> 16;
1388 *data_ptr++ = pixel >> 24;
1389 }
1390 data += bpl;
1391 }
1392
1393 #endif /* WITHOUT_SPEEDUPS */
1394 }
1395
1396 /*
1397 * write pixels into a 16-bits Z image data structure
1398 */
1399
1400 static void
PutImagePixels16(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1401 PutImagePixels16(
1402 XImage *image,
1403 unsigned int width,
1404 unsigned int height,
1405 unsigned int *pixelindex,
1406 Pixel *pixels)
1407 {
1408 unsigned char *data;
1409 unsigned int *iptr;
1410 unsigned int y;
1411
1412 #ifdef WITHOUT_SPEEDUPS
1413
1414 unsigned int x;
1415 unsigned char *addr;
1416
1417 data = (unsigned char *) image->data;
1418 iptr = pixelindex;
1419 if (image->byte_order == MSBFirst)
1420 for (y = 0; y < height; y++)
1421 for (x = 0; x < width; x++, iptr++) {
1422 addr = &data[ZINDEX16(x, y, image)];
1423 addr[0] = pixels[*iptr] >> 8;
1424 addr[1] = pixels[*iptr];
1425 }
1426 else
1427 for (y = 0; y < height; y++)
1428 for (x = 0; x < width; x++, iptr++) {
1429 addr = &data[ZINDEX16(x, y, image)];
1430 addr[0] = pixels[*iptr];
1431 addr[1] = pixels[*iptr] >> 8;
1432 }
1433
1434 #else /* WITHOUT_SPEEDUPS */
1435
1436 Pixel pixel;
1437
1438 unsigned int bpl = image->bytes_per_line;
1439 unsigned char *data_ptr, *max_data;
1440
1441 data = (unsigned char *) image->data;
1442 iptr = pixelindex;
1443 if (image->byte_order == MSBFirst)
1444 for (y = 0; y < height; y++) {
1445 data_ptr = data;
1446 max_data = data_ptr + (width << 1);
1447
1448 while (data_ptr < max_data) {
1449 pixel = pixels[*(iptr++)];
1450
1451 data_ptr[0] = pixel >> 8;
1452 data_ptr[1] = pixel;
1453
1454 data_ptr += (1 << 1);
1455 }
1456 data += bpl;
1457 }
1458 else
1459 for (y = 0; y < height; y++) {
1460 data_ptr = data;
1461 max_data = data_ptr + (width << 1);
1462
1463 while (data_ptr < max_data) {
1464 pixel = pixels[*(iptr++)];
1465
1466 data_ptr[0] = pixel;
1467 data_ptr[1] = pixel >> 8;
1468
1469 data_ptr += (1 << 1);
1470 }
1471 data += bpl;
1472 }
1473
1474 #endif /* WITHOUT_SPEEDUPS */
1475 }
1476
1477 /*
1478 * write pixels into a 8-bits Z image data structure
1479 */
1480
1481 static void
PutImagePixels8(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1482 PutImagePixels8(
1483 XImage *image,
1484 unsigned int width,
1485 unsigned int height,
1486 unsigned int *pixelindex,
1487 Pixel *pixels)
1488 {
1489 char *data;
1490 unsigned int *iptr;
1491 unsigned int y;
1492
1493 #ifdef WITHOUT_SPEEDUPS
1494
1495 unsigned int x;
1496
1497 data = image->data;
1498 iptr = pixelindex;
1499 for (y = 0; y < height; y++)
1500 for (x = 0; x < width; x++, iptr++)
1501 data[ZINDEX8(x, y, image)] = pixels[*iptr];
1502
1503 #else /* WITHOUT_SPEEDUPS */
1504
1505 unsigned int bpl = image->bytes_per_line;
1506 char *data_ptr, *max_data;
1507
1508 data = image->data;
1509 iptr = pixelindex;
1510
1511 for (y = 0; y < height; y++) {
1512 data_ptr = data;
1513 max_data = data_ptr + width;
1514
1515 while (data_ptr < max_data)
1516 *(data_ptr++) = pixels[*(iptr++)];
1517
1518 data += bpl;
1519 }
1520
1521 #endif /* WITHOUT_SPEEDUPS */
1522 }
1523
1524 /*
1525 * write pixels into a 1-bit depth image data structure and **offset null**
1526 */
1527
1528 static void
PutImagePixels1(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1529 PutImagePixels1(
1530 XImage *image,
1531 unsigned int width,
1532 unsigned int height,
1533 unsigned int *pixelindex,
1534 Pixel *pixels)
1535 {
1536 if (image->byte_order != image->bitmap_bit_order)
1537 PutImagePixels(image, width, height, pixelindex, pixels);
1538 else {
1539 unsigned int *iptr;
1540 unsigned int y;
1541 char *data;
1542
1543 #ifdef WITHOUT_SPEEDUPS
1544
1545 unsigned int x;
1546
1547 data = image->data;
1548 iptr = pixelindex;
1549 if (image->bitmap_bit_order == MSBFirst)
1550 for (y = 0; y < height; y++)
1551 for (x = 0; x < width; x++, iptr++) {
1552 if (pixels[*iptr] & 1)
1553 data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1554 else
1555 data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1556 }
1557 else
1558 for (y = 0; y < height; y++)
1559 for (x = 0; x < width; x++, iptr++) {
1560 if (pixels[*iptr] & 1)
1561 data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1562 else
1563 data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1564 }
1565
1566 #else /* WITHOUT_SPEEDUPS */
1567
1568 char value;
1569 char *data_ptr, *max_data;
1570 int bpl = image->bytes_per_line;
1571 int diff, count;
1572
1573 data = image->data;
1574 iptr = pixelindex;
1575
1576 diff = width & 7;
1577 width >>= 3;
1578
1579 if (image->bitmap_bit_order == MSBFirst)
1580 for (y = 0; y < height; y++) {
1581 data_ptr = data;
1582 max_data = data_ptr + width;
1583 while (data_ptr < max_data) {
1584 value = 0;
1585
1586 value = (value << 1) | (pixels[*(iptr++)] & 1);
1587 value = (value << 1) | (pixels[*(iptr++)] & 1);
1588 value = (value << 1) | (pixels[*(iptr++)] & 1);
1589 value = (value << 1) | (pixels[*(iptr++)] & 1);
1590 value = (value << 1) | (pixels[*(iptr++)] & 1);
1591 value = (value << 1) | (pixels[*(iptr++)] & 1);
1592 value = (value << 1) | (pixels[*(iptr++)] & 1);
1593 value = (value << 1) | (pixels[*(iptr++)] & 1);
1594
1595 *(data_ptr++) = value;
1596 }
1597 if (diff) {
1598 value = 0;
1599 for (count = 0; count < diff; count++) {
1600 if (pixels[*(iptr++)] & 1)
1601 value |= (0x80 >> count);
1602 }
1603 *(data_ptr) = value;
1604 }
1605 data += bpl;
1606 }
1607 else
1608 for (y = 0; y < height; y++) {
1609 data_ptr = data;
1610 max_data = data_ptr + width;
1611 while (data_ptr < max_data) {
1612 value = 0;
1613 iptr += 8;
1614
1615 value = (value << 1) | (pixels[*(--iptr)] & 1);
1616 value = (value << 1) | (pixels[*(--iptr)] & 1);
1617 value = (value << 1) | (pixels[*(--iptr)] & 1);
1618 value = (value << 1) | (pixels[*(--iptr)] & 1);
1619 value = (value << 1) | (pixels[*(--iptr)] & 1);
1620 value = (value << 1) | (pixels[*(--iptr)] & 1);
1621 value = (value << 1) | (pixels[*(--iptr)] & 1);
1622 value = (value << 1) | (pixels[*(--iptr)] & 1);
1623
1624 iptr += 8;
1625 *(data_ptr++) = value;
1626 }
1627 if (diff) {
1628 value = 0;
1629 for (count = 0; count < diff; count++) {
1630 if (pixels[*(iptr++)] & 1)
1631 value |= (1 << count);
1632 }
1633 *(data_ptr) = value;
1634 }
1635 data += bpl;
1636 }
1637
1638 #endif /* WITHOUT_SPEEDUPS */
1639 }
1640 }
1641
1642 int
XpmCreatePixmapFromXpmImage(Display * display,Drawable d,XpmImage * image,Pixmap * pixmap_return,Pixmap * shapemask_return,XpmAttributes * attributes)1643 XpmCreatePixmapFromXpmImage(
1644 Display *display,
1645 Drawable d,
1646 XpmImage *image,
1647 Pixmap *pixmap_return,
1648 Pixmap *shapemask_return,
1649 XpmAttributes *attributes)
1650 {
1651 XImage *ximage, *shapeimage;
1652 int ErrorStatus;
1653
1654 /* initialize return values */
1655 if (pixmap_return)
1656 *pixmap_return = 0;
1657 if (shapemask_return)
1658 *shapemask_return = 0;
1659
1660 /* create the ximages */
1661 ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1662 (pixmap_return ? &ximage : NULL),
1663 (shapemask_return ?
1664 &shapeimage : NULL),
1665 attributes);
1666 if (ErrorStatus < 0)
1667 return (ErrorStatus);
1668
1669 /* create the pixmaps and destroy images */
1670 if (pixmap_return && ximage) {
1671 xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1672 XDestroyImage(ximage);
1673 }
1674 if (shapemask_return && shapeimage) {
1675 xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1676 XDestroyImage(shapeimage);
1677 }
1678 return (ErrorStatus);
1679 }
1680
1681 # else /* AMIGA */
1682
1683 static void
APutImagePixels(XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1684 APutImagePixels (
1685 XImage *image,
1686 unsigned int width,
1687 unsigned int height,
1688 unsigned int *pixelindex,
1689 Pixel *pixels)
1690 {
1691 unsigned int *data = pixelindex;
1692 unsigned int x, y;
1693 unsigned char *array;
1694 XImage *tmp_img;
1695 BOOL success = FALSE;
1696
1697 array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
1698 if (array != NULL)
1699 {
1700 tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
1701 image->rp->BitMap->Depth);
1702 if (tmp_img != NULL)
1703 {
1704 for (y = 0; y < height; ++y)
1705 {
1706 for (x = 0; x < width; ++x)
1707 array[x] = pixels[*(data++)];
1708 WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
1709 }
1710 FreeXImage (tmp_img);
1711 success = TRUE;
1712 }
1713 XpmFree (array);
1714 }
1715
1716 if (!success)
1717 {
1718 for (y = 0; y < height; ++y)
1719 for (x = 0; x < width; ++x)
1720 XPutPixel (image, x, y, pixels[*(data++)]);
1721 }
1722 }
1723
1724 # endif/* AMIGA */
1725 #else /* FOR_MSW part follows */
1726 static void
MSWPutImagePixels(Display * dc,XImage * image,unsigned int width,unsigned int height,unsigned int * pixelindex,Pixel * pixels)1727 MSWPutImagePixels(
1728 Display *dc,
1729 XImage *image,
1730 unsigned int width,
1731 unsigned int height,
1732 unsigned int *pixelindex,
1733 Pixel *pixels)
1734 {
1735 unsigned int *data = pixelindex;
1736 unsigned int x, y;
1737 HBITMAP obm;
1738
1739 obm = SelectObject(*dc, image->bitmap);
1740 for (y = 0; y < height; y++) {
1741 for (x = 0; x < width; x++) {
1742 SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1743 }
1744 }
1745 SelectObject(*dc, obm);
1746 }
1747
1748 #endif /* FOR_MSW */
1749
1750
1751
1752 #if !defined(FOR_MSW) && !defined(AMIGA)
1753
1754 static int
PutPixel1(register XImage * ximage,int x,int y,unsigned long pixel)1755 PutPixel1(
1756 register XImage *ximage,
1757 int x,
1758 int y,
1759 unsigned long pixel)
1760 {
1761 register char *src;
1762 register char *dst;
1763 register int i;
1764 Pixel px;
1765 int nbytes;
1766
1767 if(x < 0 || y < 0)
1768 return 0;
1769
1770 for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1771 ((unsigned char *)&pixel)[i] = px;
1772 src = &ximage->data[XYINDEX(x, y, ximage)];
1773 dst = (char *)&px;
1774 px = 0;
1775 nbytes = ximage->bitmap_unit >> 3;
1776 for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1777 XYNORMALIZE(&px, ximage);
1778 i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1779 _putbits ((char *)&pixel, i, 1, (char *)&px);
1780 XYNORMALIZE(&px, ximage);
1781 src = (char *) &px;
1782 dst = &ximage->data[XYINDEX(x, y, ximage)];
1783 for (i = nbytes; --i >= 0; )
1784 *dst++ = *src++;
1785
1786 return 1;
1787 }
1788
1789 static int
PutPixel(register XImage * ximage,int x,int y,unsigned long pixel)1790 PutPixel(
1791 register XImage *ximage,
1792 int x,
1793 int y,
1794 unsigned long pixel)
1795 {
1796 register char *src;
1797 register char *dst;
1798 register int i;
1799 Pixel px;
1800 unsigned int nbytes, ibpp;
1801
1802 if(x < 0 || y < 0)
1803 return 0;
1804
1805 ibpp = ximage->bits_per_pixel;
1806 if (ximage->depth == 4)
1807 pixel &= 0xf;
1808 for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1809 ((unsigned char *) &pixel)[i] = px;
1810 src = &ximage->data[ZINDEX(x, y, ximage)];
1811 dst = (char *) &px;
1812 px = 0;
1813 nbytes = (ibpp + 7) >> 3;
1814 for (i = nbytes; --i >= 0;)
1815 *dst++ = *src++;
1816 ZNORMALIZE(&px, ximage);
1817 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1818 ZNORMALIZE(&px, ximage);
1819 src = (char *) &px;
1820 dst = &ximage->data[ZINDEX(x, y, ximage)];
1821 for (i = nbytes; --i >= 0;)
1822 *dst++ = *src++;
1823
1824 return 1;
1825 }
1826
1827 #if !defined(WORD64) && !defined(LONG64)
1828 static int
PutPixel32(register XImage * ximage,int x,int y,unsigned long pixel)1829 PutPixel32(
1830 register XImage *ximage,
1831 int x,
1832 int y,
1833 unsigned long pixel)
1834 {
1835 unsigned char *addr;
1836
1837 if(x < 0 || y < 0)
1838 return 0;
1839
1840 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1841 *((unsigned long *)addr) = pixel;
1842 return 1;
1843 }
1844 #endif
1845
1846 static int
PutPixel32MSB(register XImage * ximage,int x,int y,unsigned long pixel)1847 PutPixel32MSB(
1848 register XImage *ximage,
1849 int x,
1850 int y,
1851 unsigned long pixel)
1852 {
1853 unsigned char *addr;
1854
1855 if(x < 0 || y < 0)
1856 return 0;
1857
1858 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1859 addr[0] = pixel >> 24;
1860 addr[1] = pixel >> 16;
1861 addr[2] = pixel >> 8;
1862 addr[3] = pixel;
1863 return 1;
1864 }
1865
1866 static int
PutPixel32LSB(register XImage * ximage,int x,int y,unsigned long pixel)1867 PutPixel32LSB(
1868 register XImage *ximage,
1869 int x,
1870 int y,
1871 unsigned long pixel)
1872 {
1873 unsigned char *addr;
1874
1875 if(x < 0 || y < 0)
1876 return 0;
1877
1878 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1879 addr[3] = pixel >> 24;
1880 addr[2] = pixel >> 16;
1881 addr[1] = pixel >> 8;
1882 addr[0] = pixel;
1883 return 1;
1884 }
1885
1886 static int
PutPixel16MSB(register XImage * ximage,int x,int y,unsigned long pixel)1887 PutPixel16MSB(
1888 register XImage *ximage,
1889 int x,
1890 int y,
1891 unsigned long pixel)
1892 {
1893 unsigned char *addr;
1894
1895 if(x < 0 || y < 0)
1896 return 0;
1897
1898 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1899 addr[0] = pixel >> 8;
1900 addr[1] = pixel;
1901 return 1;
1902 }
1903
1904 static int
PutPixel16LSB(register XImage * ximage,int x,int y,unsigned long pixel)1905 PutPixel16LSB(
1906 register XImage *ximage,
1907 int x,
1908 int y,
1909 unsigned long pixel)
1910 {
1911 unsigned char *addr;
1912
1913 if(x < 0 || y < 0)
1914 return 0;
1915
1916 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1917 addr[1] = pixel >> 8;
1918 addr[0] = pixel;
1919 return 1;
1920 }
1921
1922 static int
PutPixel8(register XImage * ximage,int x,int y,unsigned long pixel)1923 PutPixel8(
1924 register XImage *ximage,
1925 int x,
1926 int y,
1927 unsigned long pixel)
1928 {
1929 if(x < 0 || y < 0)
1930 return 0;
1931
1932 ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1933 return 1;
1934 }
1935
1936 static int
PutPixel1MSB(register XImage * ximage,int x,int y,unsigned long pixel)1937 PutPixel1MSB(
1938 register XImage *ximage,
1939 int x,
1940 int y,
1941 unsigned long pixel)
1942 {
1943 if(x < 0 || y < 0)
1944 return 0;
1945
1946 if (pixel & 1)
1947 ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1948 else
1949 ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1950 return 1;
1951 }
1952
1953 static int
PutPixel1LSB(register XImage * ximage,int x,int y,unsigned long pixel)1954 PutPixel1LSB(
1955 register XImage *ximage,
1956 int x,
1957 int y,
1958 unsigned long pixel)
1959 {
1960 if(x < 0 || y < 0)
1961 return 0;
1962
1963 if (pixel & 1)
1964 ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1965 else
1966 ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1967 return 1;
1968 }
1969
1970 #endif /* not FOR_MSW && not AMIGA */
1971
1972 /*
1973 * This function parses an Xpm file or data and directly create an XImage
1974 */
1975 int
xpmParseDataAndCreate(Display * display,xpmData * data,XImage ** image_return,XImage ** shapeimage_return,XpmImage * image,XpmInfo * info,XpmAttributes * attributes)1976 xpmParseDataAndCreate(
1977 Display *display,
1978 xpmData *data,
1979 XImage **image_return,
1980 XImage **shapeimage_return,
1981 XpmImage *image,
1982 XpmInfo *info,
1983 XpmAttributes *attributes)
1984 {
1985 /* variables stored in the XpmAttributes structure */
1986 Visual *visual;
1987 Colormap colormap;
1988 unsigned int depth;
1989 int bitmap_format;
1990 XpmFreeColorsFunc freeColors;
1991
1992 /* variables to return */
1993 XImage *ximage = NULL;
1994 XImage *shapeimage = NULL;
1995 unsigned int mask_pixel_index = XpmUndefPixel;
1996
1997 /* calculation variables */
1998 Pixel *image_pixels = NULL;
1999 Pixel *mask_pixels = NULL;
2000 Pixel *alloc_pixels = NULL;
2001 Pixel *used_pixels = NULL;
2002 unsigned int nalloc_pixels = 0;
2003 unsigned int nused_pixels = 0;
2004 unsigned int width, height, ncolors, cpp;
2005 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
2006 XpmColor *colorTable = NULL;
2007 char *hints_cmt = NULL;
2008 char *colors_cmt = NULL;
2009 char *pixels_cmt = NULL;
2010
2011 unsigned int cmts;
2012 int ErrorStatus;
2013 xpmHashTable hashtable;
2014
2015
2016 /* initialize return values */
2017 if (image_return)
2018 *image_return = NULL;
2019 if (shapeimage_return)
2020 *shapeimage_return = NULL;
2021
2022
2023 /* retrieve information from the XpmAttributes */
2024 if (attributes && (attributes->valuemask & XpmVisual))
2025 visual = attributes->visual;
2026 else
2027 visual = XDefaultVisual(display, XDefaultScreen(display));
2028
2029 if (attributes && (attributes->valuemask & XpmColormap))
2030 colormap = attributes->colormap;
2031 else
2032 colormap = XDefaultColormap(display, XDefaultScreen(display));
2033
2034 if (attributes && (attributes->valuemask & XpmDepth))
2035 depth = attributes->depth;
2036 else
2037 depth = XDefaultDepth(display, XDefaultScreen(display));
2038
2039 if (attributes && (attributes->valuemask & XpmBitmapFormat))
2040 bitmap_format = attributes->bitmap_format;
2041 else
2042 bitmap_format = ZPixmap;
2043
2044 if (attributes && (attributes->valuemask & XpmFreeColors))
2045 freeColors = attributes->free_colors;
2046 else
2047 freeColors = FreeColors;
2048
2049 cmts = info && (info->valuemask & XpmReturnComments);
2050
2051 /*
2052 * parse the header
2053 */
2054 ErrorStatus = xpmParseHeader(data);
2055 if (ErrorStatus != XpmSuccess)
2056 return (ErrorStatus);
2057
2058 /*
2059 * read values
2060 */
2061 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2062 &x_hotspot, &y_hotspot, &hotspot,
2063 &extensions);
2064 if (ErrorStatus != XpmSuccess)
2065 return (ErrorStatus);
2066
2067 /*
2068 * store the hints comment line
2069 */
2070 if (cmts)
2071 xpmGetCmt(data, &hints_cmt);
2072
2073 /*
2074 * init the hashtable
2075 */
2076 if (USE_HASHTABLE) {
2077 ErrorStatus = xpmHashTableInit(&hashtable);
2078 if (ErrorStatus != XpmSuccess)
2079 RETURN(ErrorStatus);
2080 }
2081
2082 /*
2083 * read colors
2084 */
2085 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2086 if (ErrorStatus != XpmSuccess)
2087 RETURN(ErrorStatus);
2088
2089 /*
2090 * store the colors comment line
2091 */
2092 if (cmts)
2093 xpmGetCmt(data, &colors_cmt);
2094
2095 /* malloc pixels index tables */
2096 if (ncolors >= UINT_MAX / sizeof(Pixel))
2097 RETURN(XpmNoMemory);
2098
2099 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2100 if (!image_pixels)
2101 RETURN(XpmNoMemory);
2102
2103 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2104 if (!mask_pixels)
2105 RETURN(XpmNoMemory);
2106
2107 /* maximum of allocated pixels will be the number of colors */
2108 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2109 if (!alloc_pixels)
2110 RETURN(XpmNoMemory);
2111
2112 /* maximum of allocated pixels will be the number of colors */
2113 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2114 if (!used_pixels)
2115 RETURN(XpmNoMemory);
2116
2117 /* get pixel colors, store them in index tables */
2118 ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2119 image_pixels, mask_pixels, &mask_pixel_index,
2120 alloc_pixels, &nalloc_pixels, used_pixels,
2121 &nused_pixels);
2122
2123 if (ErrorStatus != XpmSuccess
2124 && (ErrorStatus < 0 || (attributes
2125 && (attributes->valuemask & XpmExactColors)
2126 && attributes->exactColors)))
2127 RETURN(ErrorStatus);
2128
2129 /* now create the ximage */
2130 if (image_return) {
2131 ErrorStatus = CreateXImage(display, visual, depth,
2132 (depth == 1 ? bitmap_format : ZPixmap),
2133 width, height, &ximage);
2134 if (ErrorStatus != XpmSuccess)
2135 RETURN(ErrorStatus);
2136
2137 #if !defined(FOR_MSW) && !defined(AMIGA)
2138
2139 /*
2140 * set the XImage pointer function, to be used with XPutPixel,
2141 * to an internal optimized function
2142 */
2143
2144 if (ximage->bits_per_pixel == 8)
2145 ximage->f.put_pixel = PutPixel8;
2146 else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2147 (ximage->byte_order == ximage->bitmap_bit_order))
2148 if (ximage->bitmap_bit_order == MSBFirst)
2149 ximage->f.put_pixel = PutPixel1MSB;
2150 else
2151 ximage->f.put_pixel = PutPixel1LSB;
2152 else if (ximage->bits_per_pixel == 16)
2153 if (ximage->bitmap_bit_order == MSBFirst)
2154 ximage->f.put_pixel = PutPixel16MSB;
2155 else
2156 ximage->f.put_pixel = PutPixel16LSB;
2157 else if (ximage->bits_per_pixel == 32)
2158 #if !defined(WORD64) && !defined(LONG64)
2159 if (*((char *)&byteorderpixel) == ximage->byte_order)
2160 ximage->f.put_pixel = PutPixel32;
2161 else
2162 #endif
2163 if (ximage->bitmap_bit_order == MSBFirst)
2164 ximage->f.put_pixel = PutPixel32MSB;
2165 else
2166 ximage->f.put_pixel = PutPixel32LSB;
2167 else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2168 ximage->f.put_pixel = PutPixel1;
2169 else
2170 ximage->f.put_pixel = PutPixel;
2171 #endif /* not FOR_MSW && not AMIGA */
2172 }
2173
2174 /* create the shape mask image */
2175 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2176 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2177 width, height, &shapeimage);
2178 if (ErrorStatus != XpmSuccess)
2179 RETURN(ErrorStatus);
2180
2181 #if !defined(FOR_MSW) && !defined(AMIGA)
2182 if (shapeimage->bitmap_bit_order == MSBFirst)
2183 shapeimage->f.put_pixel = PutPixel1MSB;
2184 else
2185 shapeimage->f.put_pixel = PutPixel1LSB;
2186 #endif
2187 }
2188
2189 /*
2190 * read pixels and put them in the XImage
2191 */
2192 ErrorStatus = ParseAndPutPixels(
2193 #ifdef FOR_MSW
2194 display,
2195 #endif
2196 data, width, height, ncolors, cpp,
2197 colorTable, &hashtable,
2198 ximage, image_pixels,
2199 shapeimage, mask_pixels);
2200 XpmFree(image_pixels);
2201 image_pixels = NULL;
2202 XpmFree(mask_pixels);
2203 mask_pixels = NULL;
2204
2205 /*
2206 * free the hastable
2207 */
2208 if (ErrorStatus != XpmSuccess)
2209 RETURN(ErrorStatus);
2210 else if (USE_HASHTABLE)
2211 xpmHashTableFree(&hashtable);
2212
2213 /*
2214 * store the pixels comment line
2215 */
2216 if (cmts)
2217 xpmGetCmt(data, &pixels_cmt);
2218
2219 /*
2220 * parse extensions
2221 */
2222 if (info && (info->valuemask & XpmReturnExtensions)) {
2223 if (extensions) {
2224 ErrorStatus = xpmParseExtensions(data, &info->extensions,
2225 &info->nextensions);
2226 if (ErrorStatus != XpmSuccess)
2227 RETURN(ErrorStatus);
2228 } else {
2229 info->extensions = NULL;
2230 info->nextensions = 0;
2231 }
2232 }
2233 /*
2234 * store found informations in the XpmImage structure
2235 */
2236 image->width = width;
2237 image->height = height;
2238 image->cpp = cpp;
2239 image->ncolors = ncolors;
2240 image->colorTable = colorTable;
2241 image->data = NULL;
2242
2243 if (info) {
2244 if (cmts) {
2245 info->hints_cmt = hints_cmt;
2246 info->colors_cmt = colors_cmt;
2247 info->pixels_cmt = pixels_cmt;
2248 }
2249 if (hotspot) {
2250 info->x_hotspot = x_hotspot;
2251 info->y_hotspot = y_hotspot;
2252 info->valuemask |= XpmHotspot;
2253 }
2254 }
2255 /* if requested return used pixels in the XpmAttributes structure */
2256 if (attributes && (attributes->valuemask & XpmReturnPixels ||
2257 /* 3.2 backward compatibility code */
2258 attributes->valuemask & XpmReturnInfos)) {
2259 /* end 3.2 bc */
2260 attributes->pixels = used_pixels;
2261 attributes->npixels = nused_pixels;
2262 attributes->mask_pixel = mask_pixel_index;
2263 } else
2264 XpmFree(used_pixels);
2265
2266 /* if requested return alloc'ed pixels in the XpmAttributes structure */
2267 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2268 attributes->alloc_pixels = alloc_pixels;
2269 attributes->nalloc_pixels = nalloc_pixels;
2270 } else
2271 XpmFree(alloc_pixels);
2272
2273 /* return created images */
2274 if (image_return)
2275 *image_return = ximage;
2276 if (shapeimage_return)
2277 *shapeimage_return = shapeimage;
2278
2279 return (XpmSuccess);
2280
2281 /* exit point in case of error, free only locally allocated variables */
2282 error:
2283 if (USE_HASHTABLE)
2284 xpmHashTableFree(&hashtable);
2285 if (colorTable)
2286 xpmFreeColorTable(colorTable, ncolors);
2287 if (hints_cmt)
2288 XpmFree(hints_cmt);
2289 if (colors_cmt)
2290 XpmFree(colors_cmt);
2291 if (pixels_cmt)
2292 XpmFree(pixels_cmt);
2293 if (ximage)
2294 XDestroyImage(ximage);
2295 if (shapeimage)
2296 XDestroyImage(shapeimage);
2297 if (image_pixels)
2298 XpmFree(image_pixels);
2299 if (mask_pixels)
2300 XpmFree(mask_pixels);
2301 if (nalloc_pixels)
2302 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
2303 if (alloc_pixels)
2304 XpmFree(alloc_pixels);
2305 if (used_pixels)
2306 XpmFree(used_pixels);
2307
2308 return (ErrorStatus);
2309 }
2310
2311 static int
ParseAndPutPixels(Display * dc,xpmData * data,unsigned int width,unsigned int height,unsigned int ncolors,unsigned int cpp,XpmColor * colorTable,xpmHashTable * hashtable,XImage * image,Pixel * image_pixels,XImage * shapeimage,Pixel * shape_pixels)2312 ParseAndPutPixels(
2313 #ifdef FOR_MSW
2314 Display *dc,
2315 #endif
2316 xpmData *data,
2317 unsigned int width,
2318 unsigned int height,
2319 unsigned int ncolors,
2320 unsigned int cpp,
2321 XpmColor *colorTable,
2322 xpmHashTable *hashtable,
2323 XImage *image,
2324 Pixel *image_pixels,
2325 XImage *shapeimage,
2326 Pixel *shape_pixels)
2327 {
2328 unsigned int a, x, y;
2329
2330 switch (cpp) {
2331
2332 case (1): /* Optimize for single character
2333 * colors */
2334 {
2335 unsigned short colidx[256];
2336 #ifdef FOR_MSW
2337 HDC shapedc;
2338 HBITMAP obm, sobm;
2339
2340 if ( shapeimage ) {
2341 shapedc = CreateCompatibleDC(*dc);
2342 sobm = SelectObject(shapedc, shapeimage->bitmap);
2343 } else {
2344 shapedc = NULL;
2345 }
2346 obm = SelectObject(*dc, image->bitmap);
2347 #endif
2348 if (ncolors > 256)
2349 return (XpmFileInvalid);
2350
2351 bzero((char *)colidx, 256 * sizeof(short));
2352 for (a = 0; a < ncolors; a++)
2353 colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2354
2355 for (y = 0; y < height; y++) {
2356 xpmNextString(data);
2357 for (x = 0; x < width; x++) {
2358 int c = xpmGetC(data);
2359
2360 if (c > 0 && c < 256 && colidx[c] != 0) {
2361 #ifndef FOR_MSW
2362 XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2363 if (shapeimage)
2364 XPutPixel(shapeimage, x, y,
2365 shape_pixels[colidx[c] - 1]);
2366 #else
2367 SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2368 if (shapedc) {
2369 SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
2370 }
2371 #endif
2372 } else
2373 return (XpmFileInvalid);
2374 }
2375 }
2376 #ifdef FOR_MSW
2377 if ( shapedc ) {
2378 SelectObject(shapedc, sobm);
2379 DeleteDC(shapedc);
2380 }
2381 SelectObject(*dc, obm);
2382 #endif
2383 }
2384 break;
2385
2386 case (2): /* Optimize for double character
2387 * colors */
2388 {
2389
2390 /* free all allocated pointers at all exits */
2391 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2392 if (cidx[f]) XpmFree(cidx[f]);}
2393
2394 /* array of pointers malloced by need */
2395 unsigned short *cidx[256];
2396 unsigned int char1;
2397
2398 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2399 for (a = 0; a < ncolors; a++) {
2400 char1 = (unsigned char) colorTable[a].string[0];
2401 if (cidx[char1] == NULL) { /* get new memory */
2402 cidx[char1] = (unsigned short *)
2403 XpmCalloc(256, sizeof(unsigned short));
2404 if (cidx[char1] == NULL) { /* new block failed */
2405 FREE_CIDX;
2406 return (XpmNoMemory);
2407 }
2408 }
2409 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2410 }
2411
2412 for (y = 0; y < height; y++) {
2413 xpmNextString(data);
2414 for (x = 0; x < width; x++) {
2415 int cc1 = xpmGetC(data);
2416 if (cc1 > 0 && cc1 < 256) {
2417 int cc2 = xpmGetC(data);
2418 if (cc2 > 0 && cc2 < 256 &&
2419 cidx[cc1] && cidx[cc1][cc2] != 0) {
2420 #ifndef FOR_MSW
2421 XPutPixel(image, x, y,
2422 image_pixels[cidx[cc1][cc2] - 1]);
2423 if (shapeimage)
2424 XPutPixel(shapeimage, x, y,
2425 shape_pixels[cidx[cc1][cc2] - 1]);
2426 #else
2427 SelectObject(*dc, image->bitmap);
2428 SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2429 if (shapeimage) {
2430 SelectObject(*dc, shapeimage->bitmap);
2431 SetPixel(*dc, x, y,
2432 shape_pixels[cidx[cc1][cc2] - 1]);
2433 }
2434 #endif
2435 } else {
2436 FREE_CIDX;
2437 return (XpmFileInvalid);
2438 }
2439 } else {
2440 FREE_CIDX;
2441 return (XpmFileInvalid);
2442 }
2443 }
2444 }
2445 FREE_CIDX;
2446 }
2447 break;
2448
2449 default: /* Non-optimized case of long color
2450 * names */
2451 {
2452 char *s;
2453 char buf[BUFSIZ];
2454
2455 if (cpp >= sizeof(buf))
2456 return (XpmFileInvalid);
2457
2458 buf[cpp] = '\0';
2459 if (USE_HASHTABLE) {
2460 xpmHashAtom *slot;
2461
2462 for (y = 0; y < height; y++) {
2463 xpmNextString(data);
2464 for (x = 0; x < width; x++) {
2465 for (a = 0, s = buf; a < cpp; a++, s++)
2466 *s = xpmGetC(data);
2467 slot = xpmHashSlot(hashtable, buf);
2468 if (!*slot) /* no color matches */
2469 return (XpmFileInvalid);
2470 #ifndef FOR_MSW
2471 XPutPixel(image, x, y,
2472 image_pixels[HashColorIndex(slot)]);
2473 if (shapeimage)
2474 XPutPixel(shapeimage, x, y,
2475 shape_pixels[HashColorIndex(slot)]);
2476 #else
2477 SelectObject(*dc, image->bitmap);
2478 SetPixel(*dc, x, y,
2479 image_pixels[HashColorIndex(slot)]);
2480 if (shapeimage) {
2481 SelectObject(*dc, shapeimage->bitmap);
2482 SetPixel(*dc, x, y,
2483 shape_pixels[HashColorIndex(slot)]);
2484 }
2485 #endif
2486 }
2487 }
2488 } else {
2489 for (y = 0; y < height; y++) {
2490 xpmNextString(data);
2491 for (x = 0; x < width; x++) {
2492 for (a = 0, s = buf; a < cpp; a++, s++)
2493 *s = xpmGetC(data);
2494 for (a = 0; a < ncolors; a++)
2495 if (!strcmp(colorTable[a].string, buf))
2496 break;
2497 if (a == ncolors) /* no color matches */
2498 return (XpmFileInvalid);
2499 #ifndef FOR_MSW
2500 XPutPixel(image, x, y, image_pixels[a]);
2501 if (shapeimage)
2502 XPutPixel(shapeimage, x, y, shape_pixels[a]);
2503 #else
2504 SelectObject(*dc, image->bitmap);
2505 SetPixel(*dc, x, y, image_pixels[a]);
2506 if (shapeimage) {
2507 SelectObject(*dc, shapeimage->bitmap);
2508 SetPixel(*dc, x, y, shape_pixels[a]);
2509 }
2510 #endif
2511 }
2512 }
2513 }
2514 }
2515 break;
2516 }
2517 return (XpmSuccess);
2518 }
2519