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