]> git.saurik.com Git - wxWidgets.git/blob - src/mac/xpm/create.c
fixed bug in scaling images
[wxWidgets.git] / src / mac / 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 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
57 char *colorname, unsigned int color_index,
58 Pixel *image_pixel, Pixel *mask_pixel,
59 unsigned int *mask_pixel_index,
60 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
61 Pixel *used_pixels, unsigned int *nused_pixels,
62 XpmAttributes *attributes, XColor *cols, int ncols,
63 XpmAllocColorFunc allocColor, void *closure));
64
65 LFUNC(CreateXImage, int, (Display *display, Visual *visual,
66 unsigned int depth, int format, unsigned int width,
67 unsigned int height, XImage **image_return));
68
69 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
70 XpmColor *colors, unsigned int ncolors,
71 Pixel *image_pixels, Pixel *mask_pixels,
72 unsigned int *mask_pixel_index,
73 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
74 Pixel *used_pixels, unsigned int *nused_pixels));
75
76 LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
77 unsigned int height, unsigned int ncolors,
78 unsigned int cpp, XpmColor *colorTable,
79 xpmHashTable *hashtable,
80 XImage *image, Pixel *image_pixels,
81 XImage *mask, Pixel *mask_pixels));
82
83 LFUNC(PlatformPutImagePixels, void, (Display *dc, XImage *image,
84 unsigned int width, unsigned int height,
85 unsigned int *pixelindex, Pixel *pixels));
86
87
88 #ifdef NEED_STRCASECMP
89 FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
90
91 /*
92 * in case strcasecmp is not provided by the system here is one
93 * which does the trick
94 */
95 int
96 xpmstrcasecmp(s1, s2)
97 register char *s1, *s2;
98 {
99 register int c1, c2;
100
101 while (*s1 && *s2) {
102 c1 = tolower(*s1);
103 c2 = tolower(*s2);
104 if (c1 != c2)
105 return (c1 - c2);
106 s1++;
107 s2++;
108 }
109 return (int) (*s1 - *s2);
110 }
111
112 #endif
113
114 /*
115 * return the default color key related to the given visual
116 */
117 static int
118 xpmVisualType(visual)
119 Visual *visual;
120 {
121 return (XPM_COLOR);
122 }
123
124
125 typedef struct {
126 int cols_index;
127 long closeness;
128 } CloseColor;
129
130 static int
131 closeness_cmp(a, b)
132 Const void *a, *b;
133 {
134 CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
135
136 /* cast to int as qsort requires */
137 return (int) (x->closeness - y->closeness);
138 }
139
140
141 /* default AllocColor function:
142 * call XParseColor if colorname is given, return negative value if failure
143 * call XAllocColor and return 0 if failure, positive otherwise
144 */
145 static int
146 AllocColor(display, colormap, colorname, xcolor, closure)
147 Display *display;
148 Colormap colormap;
149 char *colorname;
150 XColor *xcolor;
151 void *closure; /* not used */
152 {
153 int status;
154 if (colorname)
155 if (!XParseColor(display, colormap, colorname, xcolor))
156 return -1;
157 status = XAllocColor(display, colormap, xcolor);
158 return status != 0 ? 1 : 0;
159 }
160
161 /*
162 * set the color pixel related to the given colorname,
163 * return 0 if success, 1 otherwise.
164 */
165
166 static int
167 SetColor(display, colormap, visual, colorname, color_index,
168 image_pixel, mask_pixel, mask_pixel_index,
169 alloc_pixels, nalloc_pixels, used_pixels, nused_pixels,
170 attributes, cols, ncols, allocColor, closure)
171 Display *display;
172 Colormap colormap;
173 Visual *visual;
174 char *colorname;
175 unsigned int color_index;
176 Pixel *image_pixel, *mask_pixel;
177 unsigned int *mask_pixel_index;
178 Pixel *alloc_pixels;
179 unsigned int *nalloc_pixels;
180 Pixel *used_pixels;
181 unsigned int *nused_pixels;
182 XpmAttributes *attributes;
183 XColor *cols;
184 int ncols;
185 XpmAllocColorFunc allocColor;
186 void *closure;
187 {
188 XColor xcolor;
189 int status;
190
191 if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR))
192 {
193 status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
194 if (status < 0) /* parse color failed */
195 return (1);
196
197 if (status == 0) {
198 return (1);
199 } else
200 alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
201 *image_pixel = xcolor.pixel;
202
203 SET_ZERO_PIXEL( *mask_pixel );
204
205 used_pixels[(*nused_pixels)++] = xcolor.pixel;
206 }
207 else
208 {
209 // this is a special for mac - we have to get white as background for transparency
210 #ifdef macintosh
211 SET_WHITE_PIXEL( *image_pixel) ;
212 #else
213 SET_ZERO_PIXEL( *image_pixel);
214 #endif
215 SET_WHITE_PIXEL( *mask_pixel) ;
216
217 /* store the color table index */
218 *mask_pixel_index = color_index;
219 }
220 return (0);
221 }
222
223
224 static int
225 CreateColors(display, attributes, colors, ncolors, image_pixels, mask_pixels,
226 mask_pixel_index, alloc_pixels, nalloc_pixels,
227 used_pixels, nused_pixels)
228 Display *display;
229 XpmAttributes *attributes;
230 XpmColor *colors;
231 unsigned int ncolors;
232 Pixel *image_pixels;
233 Pixel *mask_pixels;
234 unsigned int *mask_pixel_index;
235 Pixel *alloc_pixels;
236 unsigned int *nalloc_pixels;
237 Pixel *used_pixels;
238 unsigned int *nused_pixels;
239 {
240 /* variables stored in the XpmAttributes structure */
241 Visual *visual;
242 Colormap colormap;
243 XpmColorSymbol *colorsymbols;
244 unsigned int numsymbols;
245 XpmAllocColorFunc allocColor;
246 void *closure;
247
248 char *colorname;
249 unsigned int color, key;
250 Bool pixel_defined;
251 XpmColorSymbol *symbol;
252 char **defaults;
253 int ErrorStatus = XpmSuccess;
254 char *s;
255 int default_index;
256
257 XColor *cols = NULL;
258 unsigned int ncols = 0;
259
260 /*
261 * retrieve information from the XpmAttributes
262 */
263 if (attributes && attributes->valuemask & XpmColorSymbols) {
264 colorsymbols = attributes->colorsymbols;
265 numsymbols = attributes->numsymbols;
266 } else
267 numsymbols = 0;
268
269 if (attributes && attributes->valuemask & XpmVisual)
270 visual = attributes->visual;
271 else
272 visual = XDefaultVisual(display, XDefaultScreen(display));
273
274 if (attributes && (attributes->valuemask & XpmColormap))
275 colormap = attributes->colormap;
276 else
277 colormap = XDefaultColormap(display, XDefaultScreen(display));
278
279 if (attributes && (attributes->valuemask & XpmColorKey))
280 key = attributes->color_key;
281 else
282 key = xpmVisualType(visual);
283
284 if (attributes && (attributes->valuemask & XpmAllocColor))
285 allocColor = attributes->alloc_color;
286 else
287 allocColor = AllocColor;
288 if (attributes && (attributes->valuemask & XpmColorClosure))
289 closure = attributes->color_closure;
290 else
291 closure = NULL;
292
293 switch (key) {
294 case XPM_MONO:
295 default_index = 2;
296 break;
297 case XPM_GRAY4:
298 default_index = 3;
299 break;
300 case XPM_GRAY:
301 default_index = 4;
302 break;
303 case XPM_COLOR:
304 default:
305 default_index = 5;
306 break;
307 }
308
309 for (color = 0; color < ncolors; color++, colors++,
310 image_pixels++, mask_pixels++) {
311 colorname = NULL;
312 pixel_defined = False;
313 defaults = (char **) colors;
314
315 /*
316 * look for a defined symbol
317 */
318 if (numsymbols) {
319
320 unsigned int n;
321
322 s = defaults[1];
323 for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
324 if (symbol->name && s && !strcmp(symbol->name, s))
325 /* override name */
326 break;
327 if (!symbol->name && symbol->value) { /* override value */
328 int def_index = default_index;
329
330 while (defaults[def_index] == NULL) /* find defined
331 * colorname */
332 --def_index;
333 if (def_index < 2) {/* nothing towards mono, so try
334 * towards color */
335 def_index = default_index + 1;
336 while (def_index <= 5 && defaults[def_index] == NULL)
337 ++def_index;
338 }
339 if (def_index >= 2 && defaults[def_index] != NULL &&
340 !xpmstrcasecmp(symbol->value, defaults[def_index]))
341 break;
342 }
343 }
344 if (n != numsymbols) {
345 if (symbol->name && symbol->value)
346 colorname = symbol->value;
347 else
348 pixel_defined = True;
349 }
350 }
351 if (!pixel_defined) { /* pixel not given as symbol value */
352
353 unsigned int k;
354
355 if (colorname) { /* colorname given as symbol value */
356 if (!SetColor(display, colormap, visual, colorname, color,
357 image_pixels, mask_pixels, mask_pixel_index,
358 alloc_pixels, nalloc_pixels, used_pixels,
359 nused_pixels, attributes, cols, ncols,
360 allocColor, closure))
361 pixel_defined = True;
362 else
363 ErrorStatus = XpmColorError;
364 }
365 k = key;
366 while (!pixel_defined && k > 1) {
367 if (defaults[k]) {
368 if (!SetColor(display, colormap, visual, defaults[k],
369 color, image_pixels, mask_pixels,
370 mask_pixel_index, alloc_pixels,
371 nalloc_pixels, used_pixels, nused_pixels,
372 attributes, cols, ncols,
373 allocColor, closure)) {
374 pixel_defined = True;
375 break;
376 } else
377 ErrorStatus = XpmColorError;
378 }
379 k--;
380 }
381 k = key + 1;
382 while (!pixel_defined && k < NKEYS + 1) {
383 if (defaults[k]) {
384 if (!SetColor(display, colormap, visual, defaults[k],
385 color, image_pixels, mask_pixels,
386 mask_pixel_index, alloc_pixels,
387 nalloc_pixels, used_pixels, nused_pixels,
388 attributes, cols, ncols,
389 allocColor, closure)) {
390 pixel_defined = True;
391 break;
392 } else
393 ErrorStatus = XpmColorError;
394 }
395 k++;
396 }
397 if (!pixel_defined) {
398 if (cols)
399 XpmFree(cols);
400 return (XpmColorFailed);
401 }
402 } else {
403 /* simply use the given pixel */
404 *image_pixels = symbol->pixel;
405 /* the following makes the mask to be built even if none
406 is given a particular pixel */
407 if (symbol->value
408 && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR))
409 {
410 SET_ZERO_PIXEL( *mask_pixels ) ;
411 *mask_pixel_index = color;
412 }
413 else
414 {
415 #ifdef macintosh
416 SET_WHITE_PIXEL( *mask_pixels ) ; // is this correct CS ????
417 #else
418 *mask_pixels = 1; // is this correct CS ????
419 #endif
420 }
421 used_pixels[(*nused_pixels)++] = *image_pixels;
422 }
423 }
424 if (cols)
425 XpmFree(cols);
426 return (ErrorStatus);
427 }
428
429
430 /* default FreeColors function, simply call XFreeColors */
431 static int
432 FreeColors(display, colormap, pixels, n, closure)
433 Display *display;
434 Colormap colormap;
435 Pixel *pixels;
436 int n;
437 void *closure; /* not used */
438 {
439 return XFreeColors(display, colormap, pixels, n, 0);
440 }
441
442
443 /* function call in case of error */
444 #undef RETURN
445 #define RETURN(status) \
446 { \
447 ErrorStatus = status; \
448 goto error; \
449 }
450
451 int
452 XpmCreateImageFromXpmImage(display, image,
453 image_return, shapeimage_return, attributes)
454 Display *display;
455 XpmImage *image;
456 XImage **image_return;
457 XImage **shapeimage_return;
458 XpmAttributes *attributes;
459 {
460 /* variables stored in the XpmAttributes structure */
461 Visual *visual;
462 Colormap colormap;
463 unsigned int depth;
464 int bitmap_format;
465 XpmFreeColorsFunc freeColors;
466 void *closure;
467
468 /* variables to return */
469 XImage *ximage = NULL;
470 XImage *shapeimage = NULL;
471 unsigned int mask_pixel_index = XpmUndefPixel;
472 int ErrorStatus;
473
474 /* calculation variables */
475 Pixel *image_pixels = NULL;
476 Pixel *mask_pixels = NULL;
477 Pixel *alloc_pixels = NULL;
478 Pixel *used_pixels = NULL;
479 unsigned int nalloc_pixels = 0;
480 unsigned int nused_pixels = 0;
481
482 /* initialize return values */
483 if (image_return)
484 *image_return = NULL;
485 if (shapeimage_return)
486 *shapeimage_return = NULL;
487
488 /* retrieve information from the XpmAttributes */
489 if (attributes && (attributes->valuemask & XpmVisual))
490 visual = attributes->visual;
491 else
492 visual = XDefaultVisual(display, XDefaultScreen(display));
493
494 if (attributes && (attributes->valuemask & XpmColormap))
495 colormap = attributes->colormap;
496 else
497 colormap = XDefaultColormap(display, XDefaultScreen(display));
498
499 if (attributes && (attributes->valuemask & XpmDepth))
500 depth = attributes->depth;
501 else
502 depth = XDefaultDepth(display, XDefaultScreen(display));
503
504 if (attributes && (attributes->valuemask & XpmBitmapFormat))
505 bitmap_format = attributes->bitmap_format;
506 else
507 bitmap_format = ZPixmap;
508
509 if (attributes && (attributes->valuemask & XpmFreeColors))
510 freeColors = attributes->free_colors;
511 else
512 freeColors = FreeColors;
513 if (attributes && (attributes->valuemask & XpmColorClosure))
514 closure = attributes->color_closure;
515 else
516 closure = NULL;
517
518 ErrorStatus = XpmSuccess;
519
520 /* malloc pixels index tables */
521 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
522 if (!image_pixels)
523 return (XpmNoMemory);
524
525 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
526 if (!mask_pixels)
527 RETURN(XpmNoMemory);
528
529 /* maximum of allocated pixels will be the number of colors */
530 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
531 if (!alloc_pixels)
532 RETURN(XpmNoMemory);
533
534 /* maximum of allocated pixels will be the number of colors */
535 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
536 if (!used_pixels)
537 RETURN(XpmNoMemory);
538
539 /* get pixel colors, store them in index tables */
540 ErrorStatus = CreateColors(display, attributes, image->colorTable,
541 image->ncolors, image_pixels, mask_pixels,
542 &mask_pixel_index, alloc_pixels, &nalloc_pixels,
543 used_pixels, &nused_pixels);
544
545 if (ErrorStatus != XpmSuccess
546 && (ErrorStatus < 0 || (attributes
547 && (attributes->valuemask & XpmExactColors)
548 && attributes->exactColors)))
549 RETURN(ErrorStatus);
550
551 /* create the ximage */
552 if (image_return) {
553 ErrorStatus = CreateXImage(display, visual, depth,
554 (depth == 1 ? bitmap_format : ZPixmap),
555 image->width, image->height, &ximage);
556 if (ErrorStatus != XpmSuccess)
557 RETURN(ErrorStatus);
558
559 PlatformPutImagePixels(display, ximage, image->width, image->height,
560 image->data, image_pixels);
561
562 }
563 /* create the shape mask image */
564 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
565 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
566 image->width, image->height, &shapeimage);
567 if (ErrorStatus != XpmSuccess)
568 RETURN(ErrorStatus);
569
570 PlatformPutImagePixels(display, shapeimage, image->width, image->height,
571 image->data, mask_pixels);
572
573 }
574 XpmFree(image_pixels);
575 XpmFree(mask_pixels);
576
577 /* if requested return used pixels in the XpmAttributes structure */
578 if (attributes && (attributes->valuemask & XpmReturnPixels ||
579 /* 3.2 backward compatibility code */
580 attributes->valuemask & XpmReturnInfos)) {
581 /* end 3.2 bc */
582 attributes->pixels = used_pixels;
583 attributes->npixels = nused_pixels;
584 attributes->mask_pixel = mask_pixel_index;
585 } else
586 XpmFree(used_pixels);
587
588 /* if requested return alloc'ed pixels in the XpmAttributes structure */
589 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
590 attributes->alloc_pixels = alloc_pixels;
591 attributes->nalloc_pixels = nalloc_pixels;
592 } else
593 XpmFree(alloc_pixels);
594
595 /* return created images */
596 if (image_return)
597 *image_return = ximage;
598 if (shapeimage_return)
599 *shapeimage_return = shapeimage;
600
601 return (ErrorStatus);
602
603 /* exit point in case of error, free only locally allocated variables */
604 error:
605 if (ximage)
606 XDestroyImage(ximage);
607 if (shapeimage)
608 XDestroyImage(shapeimage);
609 if (image_pixels)
610 XpmFree(image_pixels);
611 if (mask_pixels)
612 XpmFree(mask_pixels);
613 if (nalloc_pixels)
614 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
615 if (alloc_pixels)
616 XpmFree(alloc_pixels);
617 if (used_pixels)
618 XpmFree(used_pixels);
619
620 return (ErrorStatus);
621 }
622
623
624 /*
625 * Create an XImage with its data
626 */
627 static int
628 CreateXImage(display, visual, depth, format, width, height, image_return)
629 Display *display;
630 Visual *visual;
631 unsigned int depth;
632 int format;
633 unsigned int width;
634 unsigned int height;
635 XImage **image_return;
636 {
637 int bitmap_pad;
638
639 /* first get bitmap_pad */
640 if (depth > 16)
641 bitmap_pad = 32;
642 else if (depth > 8)
643 bitmap_pad = 16;
644 else
645 bitmap_pad = 8;
646
647 /* then create the XImage with data = NULL and bytes_per_line = 0 */
648 *image_return = XCreateImage(display, visual, depth, format, 0, 0,
649 width, height, bitmap_pad, 0);
650 if (!*image_return)
651 return (XpmNoMemory);
652
653 /* XCreateImage has done it all */
654
655 return (XpmSuccess);
656 }
657
658 static void
659 PlatformPutImagePixels(dc, image, width, height, pixelindex, pixels)
660 Display *dc;
661 XImage *image;
662 unsigned int width;
663 unsigned int height;
664 unsigned int *pixelindex;
665 Pixel *pixels;
666 {
667
668 #ifdef FOR_MSW
669 unsigned int *data = pixelindex;
670 unsigned int x, y;
671 HBITMAP obm;
672
673 obm = SelectObject(*dc, image->bitmap);
674 for (y = 0; y < height; y++) {
675 for (x = 0; x < width; x++) {
676 SetPixel(*dc, x, y, pixels[*(data++)]); // data is [x+y*width]
677 }
678 }
679 SelectObject(*dc, obm);
680 #elif macintosh
681 GrafPtr origPort ;
682 GDHandle origDevice ;
683
684 unsigned int *data = pixelindex;
685 unsigned int x, y;
686
687 GetGWorld( &origPort , &origDevice ) ;
688 SetGWorld( image->gworldptr , NULL ) ;
689
690 for (y = 0; y < height; y++)
691 {
692 for (x = 0; x < width; x++)
693 {
694 SetCPixel( x, y, &pixels[*(data++)]); // data is [x+y*width]
695 }
696 }
697 SetGWorld( origPort , origDevice ) ;
698 #endif
699 }
700
701 /*
702 * This function parses an Xpm file or data and directly create an XImage
703 */
704 int
705 xpmParseDataAndCreate(display, data, image_return, shapeimage_return,
706 image, info, attributes)
707 Display *display;
708 xpmData *data;
709 XImage **image_return;
710 XImage **shapeimage_return;
711 XpmImage *image;
712 XpmInfo *info;
713 XpmAttributes *attributes;
714 {
715 /* variables stored in the XpmAttributes structure */
716 Visual *visual;
717 Colormap colormap;
718 unsigned int depth;
719 int bitmap_format;
720 XpmFreeColorsFunc freeColors;
721 void *closure;
722
723 /* variables to return */
724 XImage *ximage = NULL;
725 XImage *shapeimage = NULL;
726 unsigned int mask_pixel_index = XpmUndefPixel;
727
728 /* calculation variables */
729 Pixel *image_pixels = NULL;
730 Pixel *mask_pixels = NULL;
731 Pixel *alloc_pixels = NULL;
732 Pixel *used_pixels = NULL;
733 unsigned int nalloc_pixels = 0;
734 unsigned int nused_pixels = 0;
735 unsigned int width, height, ncolors, cpp;
736 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
737 XpmColor *colorTable = NULL;
738 char *hints_cmt = NULL;
739 char *colors_cmt = NULL;
740 char *pixels_cmt = NULL;
741
742 unsigned int cmts;
743 int ErrorStatus;
744 xpmHashTable hashtable;
745
746
747 /* initialize return values */
748 if (image_return)
749 *image_return = NULL;
750 if (shapeimage_return)
751 *shapeimage_return = NULL;
752
753
754 /* retrieve information from the XpmAttributes */
755 if (attributes && (attributes->valuemask & XpmVisual))
756 visual = attributes->visual;
757 else
758 visual = XDefaultVisual(display, XDefaultScreen(display));
759
760 if (attributes && (attributes->valuemask & XpmColormap))
761 colormap = attributes->colormap;
762 else
763 colormap = XDefaultColormap(display, XDefaultScreen(display));
764
765 if (attributes && (attributes->valuemask & XpmDepth))
766 depth = attributes->depth;
767 else
768 depth = XDefaultDepth(display, XDefaultScreen(display));
769
770 if (attributes && (attributes->valuemask & XpmBitmapFormat))
771 bitmap_format = attributes->bitmap_format;
772 else
773 bitmap_format = ZPixmap;
774
775 if (attributes && (attributes->valuemask & XpmFreeColors))
776 freeColors = attributes->free_colors;
777 else
778 freeColors = FreeColors;
779 if (attributes && (attributes->valuemask & XpmColorClosure))
780 closure = attributes->color_closure;
781 else
782 closure = NULL;
783
784 cmts = info && (info->valuemask & XpmReturnComments);
785
786 /*
787 * parse the header
788 */
789 ErrorStatus = xpmParseHeader(data);
790 if (ErrorStatus != XpmSuccess)
791 return (ErrorStatus);
792
793 /*
794 * read values
795 */
796 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
797 &x_hotspot, &y_hotspot, &hotspot,
798 &extensions);
799 if (ErrorStatus != XpmSuccess)
800 return (ErrorStatus);
801
802 /*
803 * store the hints comment line
804 */
805 if (cmts)
806 xpmGetCmt(data, &hints_cmt);
807
808 /*
809 * init the hastable
810 */
811 if (USE_HASHTABLE) {
812 ErrorStatus = xpmHashTableInit(&hashtable);
813 if (ErrorStatus != XpmSuccess)
814 return (ErrorStatus);
815 }
816
817 /*
818 * read colors
819 */
820 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
821 if (ErrorStatus != XpmSuccess)
822 RETURN(ErrorStatus);
823
824 /*
825 * store the colors comment line
826 */
827 if (cmts)
828 xpmGetCmt(data, &colors_cmt);
829
830 /* malloc pixels index tables */
831 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
832 if (!image_pixels)
833 RETURN(XpmNoMemory);
834
835 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
836 if (!mask_pixels)
837 RETURN(XpmNoMemory);
838
839 /* maximum of allocated pixels will be the number of colors */
840 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
841 if (!alloc_pixels)
842 RETURN(XpmNoMemory);
843
844 /* maximum of allocated pixels will be the number of colors */
845 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
846 if (!used_pixels)
847 RETURN(XpmNoMemory);
848
849 /* get pixel colors, store them in index tables */
850 ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
851 image_pixels, mask_pixels, &mask_pixel_index,
852 alloc_pixels, &nalloc_pixels, used_pixels,
853 &nused_pixels);
854
855 if (ErrorStatus != XpmSuccess
856 && (ErrorStatus < 0 || (attributes
857 && (attributes->valuemask & XpmExactColors)
858 && attributes->exactColors)))
859 RETURN(ErrorStatus);
860
861 /* now create the ximage */
862 if (image_return) {
863 ErrorStatus = CreateXImage(display, visual, depth,
864 (depth == 1 ? bitmap_format : ZPixmap),
865 width, height, &ximage);
866 if (ErrorStatus != XpmSuccess)
867 RETURN(ErrorStatus);
868
869 }
870
871 /* create the shape mask image */
872 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
873 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
874 width, height, &shapeimage);
875 if (ErrorStatus != XpmSuccess)
876 RETURN(ErrorStatus);
877
878 }
879
880 /*
881 * read pixels and put them in the XImage
882 */
883 ErrorStatus = ParseAndPutPixels(
884 display,
885 data, width, height, ncolors, cpp,
886 colorTable, &hashtable,
887 ximage, image_pixels,
888 shapeimage, mask_pixels);
889 XpmFree(image_pixels);
890 image_pixels = NULL;
891 XpmFree(mask_pixels);
892 mask_pixels = NULL;
893
894 /*
895 * free the hastable
896 */
897 if (ErrorStatus != XpmSuccess)
898 RETURN(ErrorStatus)
899 else if (USE_HASHTABLE)
900 xpmHashTableFree(&hashtable);
901
902 /*
903 * store the pixels comment line
904 */
905 if (cmts)
906 xpmGetCmt(data, &pixels_cmt);
907
908 /*
909 * parse extensions
910 */
911 if (info && (info->valuemask & XpmReturnExtensions))
912 if (extensions) {
913 ErrorStatus = xpmParseExtensions(data, &info->extensions,
914 &info->nextensions);
915 if (ErrorStatus != XpmSuccess)
916 RETURN(ErrorStatus);
917 } else {
918 info->extensions = NULL;
919 info->nextensions = 0;
920 }
921
922 /*
923 * store found informations in the XpmImage structure
924 */
925 image->width = width;
926 image->height = height;
927 image->cpp = cpp;
928 image->ncolors = ncolors;
929 image->colorTable = colorTable;
930 image->data = NULL;
931
932 if (info) {
933 if (cmts) {
934 info->hints_cmt = hints_cmt;
935 info->colors_cmt = colors_cmt;
936 info->pixels_cmt = pixels_cmt;
937 }
938 if (hotspot) {
939 info->x_hotspot = x_hotspot;
940 info->y_hotspot = y_hotspot;
941 info->valuemask |= XpmHotspot;
942 }
943 }
944 /* if requested return used pixels in the XpmAttributes structure */
945 if (attributes && (attributes->valuemask & XpmReturnPixels ||
946 /* 3.2 backward compatibility code */
947 attributes->valuemask & XpmReturnInfos)) {
948 /* end 3.2 bc */
949 attributes->pixels = used_pixels;
950 attributes->npixels = nused_pixels;
951 attributes->mask_pixel = mask_pixel_index;
952 } else
953 XpmFree(used_pixels);
954
955 /* if requested return alloc'ed pixels in the XpmAttributes structure */
956 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
957 attributes->alloc_pixels = alloc_pixels;
958 attributes->nalloc_pixels = nalloc_pixels;
959 } else
960 XpmFree(alloc_pixels);
961
962 /* return created images */
963 if (image_return)
964 *image_return = ximage;
965 if (shapeimage_return)
966 *shapeimage_return = shapeimage;
967
968 return (XpmSuccess);
969
970 /* exit point in case of error, free only locally allocated variables */
971 error:
972 if (USE_HASHTABLE)
973 xpmHashTableFree(&hashtable);
974 if (colorTable)
975 xpmFreeColorTable(colorTable, ncolors);
976 if (hints_cmt)
977 XpmFree(hints_cmt);
978 if (colors_cmt)
979 XpmFree(colors_cmt);
980 if (pixels_cmt)
981 XpmFree(pixels_cmt);
982 if (ximage)
983 XDestroyImage(ximage);
984 if (shapeimage)
985 XDestroyImage(shapeimage);
986 if (image_pixels)
987 XpmFree(image_pixels);
988 if (mask_pixels)
989 XpmFree(mask_pixels);
990 if (nalloc_pixels)
991 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
992 if (alloc_pixels)
993 XpmFree(alloc_pixels);
994 if (used_pixels)
995 XpmFree(used_pixels);
996
997 return (ErrorStatus);
998 }
999
1000 static int
1001 ParseAndPutPixels(
1002 dc,
1003 data, width, height, ncolors, cpp, colorTable, hashtable,
1004 image, image_pixels, shapeimage, shape_pixels)
1005 Display *dc;
1006 xpmData *data;
1007 unsigned int width;
1008 unsigned int height;
1009 unsigned int ncolors;
1010 unsigned int cpp;
1011 XpmColor *colorTable;
1012 xpmHashTable *hashtable;
1013 XImage *image;
1014 Pixel *image_pixels;
1015 XImage *shapeimage;
1016 Pixel *shape_pixels;
1017 {
1018 unsigned int a, x, y;
1019
1020 switch (cpp) {
1021
1022 case (1): /* Optimize for single character
1023 * colors */
1024 {
1025 unsigned short colidx[256];
1026 #ifdef FOR_MSW
1027
1028 HDC shapedc;
1029 HBITMAP obm, sobm;
1030
1031 if ( shapeimage ) {
1032 shapedc = CreateCompatibleDC(*dc);
1033 sobm = SelectObject(shapedc, shapeimage->bitmap);
1034 } else {
1035 shapedc = NULL;
1036 }
1037 obm = SelectObject(*dc, image->bitmap);
1038
1039 #elif macintosh
1040 GrafPtr origPort ;
1041 GDHandle origDevice ;
1042
1043 GetGWorld( &origPort , &origDevice ) ;
1044 // ignore shapedc
1045 SetGWorld( image->gworldptr , NULL ) ;
1046
1047 #endif
1048
1049 bzero((char *)colidx, 256 * sizeof(short));
1050 for (a = 0; a < ncolors; a++)
1051 colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
1052
1053 for (y = 0; y < height; y++)
1054 {
1055 xpmNextString(data);
1056 for (x = 0; x < width; x++)
1057 {
1058 int c = xpmGetC(data);
1059
1060 if (c > 0 && c < 256 && colidx[c] != 0)
1061 {
1062 #if FOR_MSW
1063 SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
1064 if (shapedc)
1065 {
1066 SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
1067 }
1068 #elif macintosh
1069 SetCPixel( x, y, &image_pixels[colidx[c] - 1]);
1070 /*
1071 if (shapedc)
1072 {
1073 SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
1074 }
1075 */
1076 #endif
1077 }
1078 else
1079 return (XpmFileInvalid);
1080 }
1081 }
1082 #if FOR_MSW
1083 if ( shapedc )
1084 {
1085 SelectObject(shapedc, sobm);
1086 DeleteDC(shapedc);
1087 }
1088 SelectObject(*dc, obm);
1089 #elif macintosh
1090 SetGWorld( origPort , origDevice ) ;
1091 #endif
1092 }
1093 break;
1094
1095 case (2): /* Optimize for double character
1096 * colors */
1097 {
1098
1099 /* free all allocated pointers at all exits */
1100 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
1101 if (cidx[f]) XpmFree(cidx[f]);}
1102
1103 /* array of pointers malloced by need */
1104 unsigned short *cidx[256];
1105 int char1;
1106 #ifdef macintosh
1107 GrafPtr origPort ;
1108 GDHandle origDevice ;
1109 GetGWorld( &origPort , &origDevice ) ;
1110 SetGWorld( image->gworldptr , NULL ) ;
1111 #endif
1112 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
1113 for (a = 0; a < ncolors; a++) {
1114 char1 = colorTable[a].string[0];
1115 if (cidx[char1] == NULL) { /* get new memory */
1116 cidx[char1] = (unsigned short *)
1117 XpmCalloc(256, sizeof(unsigned short));
1118 if (cidx[char1] == NULL) { /* new block failed */
1119 #ifdef macintosh
1120 SetGWorld( origPort , origDevice ) ;
1121 #endif
1122 FREE_CIDX;
1123 return (XpmNoMemory);
1124 }
1125 }
1126 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
1127 }
1128
1129 for (y = 0; y < height; y++) {
1130 xpmNextString(data);
1131 for (x = 0; x < width; x++)
1132 {
1133 int cc1 = xpmGetC(data);
1134 if (cc1 > 0 && cc1 < 256) {
1135 int cc2 = xpmGetC(data);
1136 if (cc2 > 0 && cc2 < 256 &&
1137 cidx[cc1] && cidx[cc1][cc2] != 0) {
1138
1139 #ifdef FOR_MSW
1140 SelectObject(*dc, image->bitmap);
1141 SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
1142 if (shapeimage)
1143 {
1144 SelectObject(*dc, shapeimage->bitmap);
1145 SetPixel(*dc, x, y,
1146 shape_pixels[cidx[cc1][cc2] - 1]);
1147 }
1148 #elif macintosh
1149 SetCPixel( x, y, &image_pixels[cidx[cc1][cc2] - 1]);
1150 #endif
1151 } else
1152 {
1153 #ifdef macintosh
1154 SetGWorld( origPort , origDevice ) ;
1155 #endif
1156 FREE_CIDX;
1157 return (XpmFileInvalid);
1158 }
1159 } else {
1160 #ifdef macintosh
1161 SetGWorld( origPort , origDevice ) ;
1162 #endif
1163 FREE_CIDX;
1164 return (XpmFileInvalid);
1165 }
1166 }
1167 }
1168 #ifdef macintosh
1169 SetGWorld( origPort , origDevice ) ;
1170 #endif
1171 FREE_CIDX;
1172 }
1173 break;
1174
1175 default: /* Non-optimized case of long color
1176 * names */
1177 {
1178 char *s;
1179 char buf[BUFSIZ];
1180 #ifdef macintosh
1181 GrafPtr origPort ;
1182 GDHandle origDevice ;
1183 GetGWorld( &origPort , &origDevice ) ;
1184 SetGWorld( image->gworldptr , NULL ) ;
1185 #endif
1186
1187 buf[cpp] = '\0';
1188 if (USE_HASHTABLE) {
1189 xpmHashAtom *slot;
1190
1191 for (y = 0; y < height; y++) {
1192 xpmNextString(data);
1193 for (x = 0; x < width; x++) {
1194 for (a = 0, s = buf; a < cpp; a++, s++)
1195 *s = xpmGetC(data);
1196 slot = xpmHashSlot(hashtable, buf);
1197 if (!*slot) /* no color matches */
1198 {
1199 #ifdef macintosh
1200 SetGWorld( origPort , origDevice ) ;
1201 #endif
1202 return (XpmFileInvalid);
1203 }
1204
1205 #if FOR_MSW
1206 SelectObject(*dc, image->bitmap);
1207 SetPixel(*dc, x, y,
1208 image_pixels[HashColorIndex(slot)]);
1209 if (shapeimage)
1210 {
1211 SelectObject(*dc, shapeimage->bitmap);
1212 SetPixel(*dc, x, y,
1213 shape_pixels[HashColorIndex(slot)]);
1214 }
1215 #elif macintosh
1216 SetCPixel( x, y, &image_pixels[HashColorIndex(slot)]);
1217 #endif
1218 }
1219 }
1220 } else {
1221 for (y = 0; y < height; y++) {
1222 xpmNextString(data);
1223 for (x = 0; x < width; x++) {
1224 for (a = 0, s = buf; a < cpp; a++, s++)
1225 *s = xpmGetC(data);
1226 for (a = 0; a < ncolors; a++)
1227 if (!strcmp(colorTable[a].string, buf))
1228 break;
1229 if (a == ncolors) /* no color matches */
1230 {
1231 #ifdef macintosh
1232 SetGWorld( origPort , origDevice ) ;
1233 #endif
1234 return (XpmFileInvalid);
1235 }
1236
1237 #if FOR_MSW
1238 SelectObject(*dc, image->bitmap);
1239 SetPixel(*dc, x, y, image_pixels[a]);
1240 if (shapeimage) {
1241 SelectObject(*dc, shapeimage->bitmap);
1242 SetPixel(*dc, x, y, shape_pixels[a]);
1243 }
1244 #elif macintosh
1245 SetCPixel( x, y, &image_pixels[a]); // data is [x+y*width]
1246 #endif
1247 }
1248 }
1249 }
1250 #ifdef macintosh
1251 SetGWorld( origPort , origDevice ) ;
1252 #endif
1253
1254 }
1255 break;
1256 }
1257 return (XpmSuccess);
1258 }