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