2 * Copyright (C) 1989-95 GROUPE BULL
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
26 /*****************************************************************************\
30 * Create an X image and possibly its related shape mask *
31 * from the given XpmImage. *
33 * Developed by Arnaud Le Hors *
34 \*****************************************************************************/
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
42 * The code related to AMIGA has been added by
43 * Lorens Younes (d93-hyo@nada.kth.se) 4/96
46 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
54 LFUNC(xpmVisualType, int, (Visual *visual));
56 LFUNC(AllocColor, int, (Display *display, Colormap colormap,
57 char *colorname, XColor *xcolor, void *closure));
58 LFUNC(FreeColors, int, (Display *display, Colormap colormap,
59 Pixel *pixels, int n, void *closure));
62 LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
63 Visual *visual, XColor *col,
64 Pixel *image_pixel, Pixel *mask_pixel,
65 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
66 XpmAttributes *attributes, XColor *cols, int ncols,
67 XpmAllocColorFunc allocColor, void *closure));
69 /* let the window system take care of close colors */
72 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
73 char *colorname, unsigned int color_index,
74 Pixel *image_pixel, Pixel *mask_pixel,
75 unsigned int *mask_pixel_index,
76 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
77 Pixel *used_pixels, unsigned int *nused_pixels,
78 XpmAttributes *attributes, XColor *cols, int ncols,
79 XpmAllocColorFunc allocColor, void *closure));
81 LFUNC(CreateXImage, int, (Display *display, Visual *visual,
82 unsigned int depth, int format, unsigned int width,
83 unsigned int height, XImage **image_return));
85 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
86 XpmColor *colors, unsigned int ncolors,
87 Pixel *image_pixels, Pixel *mask_pixels,
88 unsigned int *mask_pixel_index,
89 Pixel *alloc_pixels, unsigned int *nalloc_pixels,
90 Pixel *used_pixels, unsigned int *nused_pixels));
93 LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
94 unsigned int height, unsigned int ncolors,
95 unsigned int cpp, XpmColor *colorTable,
96 xpmHashTable *hashtable,
97 XImage *image, Pixel *image_pixels,
98 XImage *mask, Pixel *mask_pixels));
100 LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
101 unsigned int height, unsigned int ncolors,
102 unsigned int cpp, XpmColor *colorTable,
103 xpmHashTable *hashtable,
104 XImage *image, Pixel *image_pixels,
105 XImage *mask, Pixel *mask_pixels));
110 /* XImage pixel routines */
111 LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
112 unsigned int height, unsigned int *pixelindex,
115 LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
116 unsigned int height, unsigned int *pixelindex,
119 LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
120 unsigned int height, unsigned int *pixelindex,
123 LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
124 unsigned int height, unsigned int *pixelindex,
127 LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
128 unsigned int height, unsigned int *pixelindex,
131 LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
132 LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
133 #if !defined(WORD64) && !defined(LONG64)
134 LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
136 LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
137 LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
138 LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
139 LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
140 LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
141 LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
142 LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
145 LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width,
146 unsigned int height, unsigned int *pixelindex,
150 /* FOR_MSW pixel routine */
151 LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
152 unsigned int width, unsigned int height,
153 unsigned int *pixelindex, Pixel *pixels));
156 #ifdef NEED_STRCASECMP
157 FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
160 * in case strcasecmp is not provided by the system here is one
161 * which does the trick
178 return (int) (*s1 - *s2);
184 * return the default color key related to the given visual
187 xpmVisualType(Visual *visual)
191 switch (visual->class) {
194 switch (visual->map_entries) {
206 /* set the key explicitly in the XpmAttributes to override this */
210 /* there should be a similar switch for MSW */
222 closeness_cmp(const void *a, const void *b)
224 const CloseColor *x = (const CloseColor *) a, *y = (const CloseColor *) b;
226 /* cast to int as qsort requires */
227 return (int) (x->closeness - y->closeness);
231 /* default AllocColor function:
232 * call XParseColor if colorname is given, return negative value if failure
233 * call XAllocColor and return 0 if failure, positive otherwise
241 void *closure) /* not used */
245 if (!XParseColor(display, colormap, colorname, xcolor))
247 status = XAllocColor(display, colormap, xcolor);
248 return status != 0 ? 1 : 0;
254 * set a close color in case the exact one can't be set
255 * return 0 if success, 1 otherwise.
267 unsigned int *nalloc_pixels,
268 XpmAttributes *attributes,
271 XpmAllocColorFunc allocColor,
276 * Allocation failed, so try close colors. To get here the visual must
277 * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
278 * What about sharing systems like QDSS?). Beware: we have to treat
279 * DirectColor differently.
283 long int red_closeness, green_closeness, blue_closeness;
287 if (attributes && (attributes->valuemask & XpmCloseness))
288 red_closeness = green_closeness = blue_closeness =
289 attributes->closeness;
291 red_closeness = attributes->red_closeness;
292 green_closeness = attributes->green_closeness;
293 blue_closeness = attributes->blue_closeness;
295 if (attributes && (attributes->valuemask & XpmAllocCloseColors))
296 alloc_color = attributes->alloc_close_colors;
301 * We sort the colormap by closeness and try to allocate the color
302 * closest to the target. If the allocation of this close color fails,
303 * which almost never happens, then one of two scenarios is possible.
304 * Either the colormap must have changed (since the last close color
305 * allocation or possibly while we were sorting the colormap), or the
306 * color is allocated as Read/Write by some other client. (Note: X
307 * _should_ allow clients to check if a particular color is Read/Write,
308 * but it doesn't! :-( ). We cannot determine which of these scenarios
309 * occurred, so we try the next closest color, and so on, until no more
310 * colors are within closeness of the target. If we knew that the
311 * colormap had changed, we could skip this sequence.
313 * If _none_ of the colors within closeness of the target can be allocated,
314 * then we can finally be pretty sure that the colormap has actually
315 * changed. In this case we try to allocate the original color (again),
316 * then try the closecolor stuff (again)...
318 * In theory it would be possible for an infinite loop to occur if another
319 * process kept changing the colormap every time we sorted it, so we set
320 * a maximum on the number of iterations. After this many tries, we use
321 * XGrabServer() to ensure that the colormap remains unchanged.
323 * This approach gives particularly bad worst case performance - as many as
324 * <MaximumIterations> colormap reads and sorts may be needed, and as
325 * many as <MaximumIterations> * <ColormapSize> attempted allocations
326 * may fail. On an 8-bit system, this means as many as 3 colormap reads,
327 * 3 sorts and 768 failed allocations per execution of this code!
328 * Luckily, my experiments show that in general use in a typical 8-bit
329 * color environment only about 1 in every 10000 allocations fails to
330 * succeed in the fastest possible time. So virtually every time what
331 * actually happens is a single sort followed by a successful allocate.
332 * The very first allocation also costs a colormap read, but no further
333 * reads are usually necessary.
336 #define ITERATIONS 2 /* more than one is almost never
339 for (n = 0; n <= ITERATIONS; ++n) {
340 CloseColor *closenesses =
341 (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
344 for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */
345 #define COLOR_FACTOR 3
346 #define BRIGHTNESS_FACTOR 1
348 closenesses[i].cols_index = i;
349 closenesses[i].closeness =
350 COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
351 + abs((long) col->green - (long) cols[i].green)
352 + abs((long) col->blue - (long) cols[i].blue))
353 + BRIGHTNESS_FACTOR * abs(((long) col->red +
356 - ((long) cols[i].red +
357 (long) cols[i].green +
358 (long) cols[i].blue));
360 qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
363 c = closenesses[i].cols_index;
364 while ((long) cols[c].red >= (long) col->red - red_closeness &&
365 (long) cols[c].red <= (long) col->red + red_closeness &&
366 (long) cols[c].green >= (long) col->green - green_closeness &&
367 (long) cols[c].green <= (long) col->green + green_closeness &&
368 (long) cols[c].blue >= (long) col->blue - blue_closeness &&
369 (long) cols[c].blue <= (long) col->blue + blue_closeness) {
371 if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
373 XUngrabServer(display);
374 XpmFree(closenesses);
375 *image_pixel = cols[c].pixel;
377 alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
383 c = closenesses[i].cols_index;
387 XUngrabServer(display);
388 XpmFree(closenesses);
389 *image_pixel = cols[c].pixel;
395 /* Couldn't allocate _any_ of the close colors! */
398 XUngrabServer(display);
399 XpmFree(closenesses);
401 if (i == 0 || i == ncols) /* no color close enough or cannot */
402 return (1); /* alloc any color (full of r/w's) */
404 if ((*allocColor)(display, colormap, NULL, col, closure)) {
405 *image_pixel = col->pixel;
407 alloc_pixels[(*nalloc_pixels)++] = col->pixel;
409 } else { /* colormap has probably changed, so
411 if (n == ITERATIONS - 1)
412 XGrabServer(display);
415 if (visual->class == DirectColor) {
419 XQueryColors(display, colormap, cols, ncols);
425 #define USE_CLOSECOLOR attributes && \
426 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
427 || ((attributes->valuemask & XpmRGBCloseness) && \
428 (attributes->red_closeness != 0 \
429 || attributes->green_closeness != 0 \
430 || attributes->blue_closeness != 0)))
434 /* nothing to do here, the window system does it */
438 * set the color pixel related to the given colorname,
439 * return 0 if success, 1 otherwise.
448 unsigned int color_index,
451 unsigned int *mask_pixel_index,
453 unsigned int *nalloc_pixels,
455 unsigned int *nused_pixels,
456 XpmAttributes *attributes,
459 XpmAllocColorFunc allocColor,
465 if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
466 status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
467 if (status < 0) /* parse color failed */
473 return (SetCloseColor(display, colormap, visual, &xcolor,
474 image_pixel, mask_pixel,
475 alloc_pixels, nalloc_pixels,
476 attributes, cols, ncols,
477 allocColor, closure));
479 #endif /* ndef FOR_MSW */
482 alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
483 *image_pixel = xcolor.pixel;
487 *mask_pixel = RGB(0,0,0);
489 used_pixels[(*nused_pixels)++] = xcolor.pixel;
495 *mask_pixel = RGB(255,255,255);
497 /* store the color table index */
498 *mask_pixel_index = color_index;
507 XpmAttributes *attributes,
509 unsigned int ncolors,
512 unsigned int *mask_pixel_index,
514 unsigned int *nalloc_pixels,
516 unsigned int *nused_pixels)
518 /* variables stored in the XpmAttributes structure */
521 XpmColorSymbol *colorsymbols = NULL;
522 unsigned int numsymbols;
523 XpmAllocColorFunc allocColor;
527 unsigned int color, key;
529 XpmColorSymbol *symbol = NULL;
531 int ErrorStatus = XpmSuccess;
536 unsigned int ncols = 0;
539 * retrieve information from the XpmAttributes
541 if (attributes && attributes->valuemask & XpmColorSymbols) {
542 colorsymbols = attributes->colorsymbols;
543 numsymbols = attributes->numsymbols;
547 if (attributes && attributes->valuemask & XpmVisual)
548 visual = attributes->visual;
550 visual = XDefaultVisual(display, XDefaultScreen(display));
552 if (attributes && (attributes->valuemask & XpmColormap))
553 colormap = attributes->colormap;
555 colormap = XDefaultColormap(display, XDefaultScreen(display));
557 if (attributes && (attributes->valuemask & XpmColorKey))
558 key = attributes->color_key;
560 key = xpmVisualType(visual);
562 if (attributes && (attributes->valuemask & XpmAllocColor))
563 allocColor = attributes->alloc_color;
565 allocColor = AllocColor;
566 if (attributes && (attributes->valuemask & XpmColorClosure))
567 closure = attributes->color_closure;
572 if (USE_CLOSECOLOR) {
573 /* originally from SetCloseColor */
575 if (visual->class == DirectColor) {
578 * TODO: Implement close colors for DirectColor visuals. This is
579 * difficult situation. Chances are that we will never get here,
580 * because any machine that supports DirectColor will probably
581 * also support TrueColor (and probably PseudoColor). Also,
582 * DirectColor colormaps can be very large, so looking for close
583 * colors may be too slow.
590 ncols = visual->map_entries;
592 ncols = colormap->Count;
594 cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
595 for (i = 0; i < ncols; ++i)
597 XQueryColors(display, colormap, cols, ncols);
602 #endif /* ndef FOR_MSW */
620 for (color = 0; color < ncolors; color++, colors++,
621 image_pixels++, mask_pixels++) {
623 pixel_defined = False;
624 defaults = (char **) colors;
627 * look for a defined symbol
634 for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
635 if (symbol->name && s && !strcmp(symbol->name, s))
638 if (!symbol->name && symbol->value) { /* override value */
639 int def_index = default_index;
641 while (defaults[def_index] == NULL) /* find defined
644 if (def_index < 2) {/* nothing towards mono, so try
646 def_index = default_index + 1;
647 while (def_index <= 5 && defaults[def_index] == NULL)
650 if (def_index >= 2 && defaults[def_index] != NULL &&
651 !xpmstrcasecmp(symbol->value, defaults[def_index]))
655 if (n != numsymbols) {
656 if (symbol->name && symbol->value)
657 colorname = symbol->value;
659 pixel_defined = True;
662 if (!pixel_defined) { /* pixel not given as symbol value */
666 if (colorname) { /* colorname given as symbol value */
667 if (!SetColor(display, colormap, visual, colorname, color,
668 image_pixels, mask_pixels, mask_pixel_index,
669 alloc_pixels, nalloc_pixels, used_pixels,
670 nused_pixels, attributes, cols, ncols,
671 allocColor, closure))
672 pixel_defined = True;
674 ErrorStatus = XpmColorError;
677 while (!pixel_defined && k > 1) {
679 if (!SetColor(display, colormap, visual, defaults[k],
680 color, image_pixels, mask_pixels,
681 mask_pixel_index, alloc_pixels,
682 nalloc_pixels, used_pixels, nused_pixels,
683 attributes, cols, ncols,
684 allocColor, closure)) {
685 pixel_defined = True;
688 ErrorStatus = XpmColorError;
693 while (!pixel_defined && k < NKEYS + 1) {
695 if (!SetColor(display, colormap, visual, defaults[k],
696 color, image_pixels, mask_pixels,
697 mask_pixel_index, alloc_pixels,
698 nalloc_pixels, used_pixels, nused_pixels,
699 attributes, cols, ncols,
700 allocColor, closure)) {
701 pixel_defined = True;
704 ErrorStatus = XpmColorError;
708 if (!pixel_defined) {
711 return (XpmColorFailed);
714 /* simply use the given pixel */
715 *image_pixels = symbol->pixel;
716 /* the following makes the mask to be built even if none
717 is given a particular pixel */
719 && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
721 *mask_pixel_index = color;
724 used_pixels[(*nused_pixels)++] = *image_pixels;
729 return (ErrorStatus);
733 /* default FreeColors function, simply call XFreeColors */
740 void *closure) /* not used */
742 return XFreeColors(display, colormap, pixels, n, 0);
746 /* function call in case of error */
749 #define RETURN(status) \
752 ErrorStatus = status; \
757 XpmCreateImageFromXpmImage(
760 XImage **image_return,
761 XImage **shapeimage_return,
762 XpmAttributes *attributes)
764 /* variables stored in the XpmAttributes structure */
769 XpmFreeColorsFunc freeColors;
771 /* variables to return */
772 XImage *ximage = NULL;
773 XImage *shapeimage = NULL;
774 unsigned int mask_pixel_index = XpmUndefPixel;
777 /* calculation variables */
778 Pixel *image_pixels = NULL;
779 Pixel *mask_pixels = NULL;
780 Pixel *alloc_pixels = NULL;
781 Pixel *used_pixels = NULL;
782 unsigned int nalloc_pixels = 0;
783 unsigned int nused_pixels = 0;
785 /* initialize return values */
787 *image_return = NULL;
788 if (shapeimage_return)
789 *shapeimage_return = NULL;
791 /* retrieve information from the XpmAttributes */
792 if (attributes && (attributes->valuemask & XpmVisual))
793 visual = attributes->visual;
795 visual = XDefaultVisual(display, XDefaultScreen(display));
797 if (attributes && (attributes->valuemask & XpmColormap))
798 colormap = attributes->colormap;
800 colormap = XDefaultColormap(display, XDefaultScreen(display));
802 if (attributes && (attributes->valuemask & XpmDepth))
803 depth = attributes->depth;
805 depth = XDefaultDepth(display, XDefaultScreen(display));
807 if (attributes && (attributes->valuemask & XpmBitmapFormat))
808 bitmap_format = attributes->bitmap_format;
810 bitmap_format = ZPixmap;
812 if (attributes && (attributes->valuemask & XpmFreeColors))
813 freeColors = attributes->free_colors;
815 freeColors = FreeColors;
817 ErrorStatus = XpmSuccess;
819 if (image->ncolors >= UINT_MAX / sizeof(Pixel))
820 return (XpmNoMemory);
822 /* malloc pixels index tables */
823 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
825 return (XpmNoMemory);
827 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
831 /* maximum of allocated pixels will be the number of colors */
832 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
836 /* maximum of allocated pixels will be the number of colors */
837 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
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);
847 if (ErrorStatus != XpmSuccess
848 && (ErrorStatus < 0 || (attributes
849 && (attributes->valuemask & XpmExactColors)
850 && attributes->exactColors)))
853 /* create the ximage */
855 ErrorStatus = CreateXImage(display, visual, depth,
856 (depth == 1 ? bitmap_format : ZPixmap),
857 image->width, image->height, &ximage);
858 if (ErrorStatus != XpmSuccess)
865 * set the ximage data using optimized functions for ZPixmap
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);
882 PutImagePixels(ximage, image->width, image->height,
883 image->data, image_pixels);
885 APutImagePixels(ximage, image->width, image->height,
886 image->data, image_pixels);
889 MSWPutImagePixels(display, ximage, image->width, image->height,
890 image->data, image_pixels);
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)
902 PutImagePixels1(shapeimage, image->width, image->height,
903 image->data, mask_pixels);
905 APutImagePixels(shapeimage, image->width, image->height,
906 image->data, mask_pixels);
909 MSWPutImagePixels(display, shapeimage, image->width, image->height,
910 image->data, mask_pixels);
914 XpmFree(image_pixels);
915 XpmFree(mask_pixels);
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)) {
922 attributes->pixels = used_pixels;
923 attributes->npixels = nused_pixels;
924 attributes->mask_pixel = mask_pixel_index;
926 XpmFree(used_pixels);
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;
933 XpmFree(alloc_pixels);
935 /* return created images */
937 *image_return = ximage;
938 if (shapeimage_return)
939 *shapeimage_return = shapeimage;
941 return (ErrorStatus);
943 /* exit point in case of error, free only locally allocated variables */
946 XDestroyImage(ximage);
948 XDestroyImage(shapeimage);
950 XpmFree(image_pixels);
952 XpmFree(mask_pixels);
954 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
956 XpmFree(alloc_pixels);
958 XpmFree(used_pixels);
960 return (ErrorStatus);
965 * Create an XImage with its data
975 XImage **image_return)
979 /* first get bitmap_pad */
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);
991 return (XpmNoMemory);
993 #if !defined(FOR_MSW) && !defined(AMIGA)
994 if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
995 XDestroyImage(*image_return);
998 /* now that bytes_per_line must have been set properly alloc data */
999 if((*image_return)->bytes_per_line == 0 || height == 0)
1001 (*image_return)->data =
1002 (char *) XpmMalloc((*image_return)->bytes_per_line * height);
1004 if (!(*image_return)->data) {
1005 XDestroyImage(*image_return);
1006 *image_return = NULL;
1007 return (XpmNoMemory);
1010 /* under FOR_MSW and AMIGA XCreateImage has done it all */
1012 return (XpmSuccess);
1018 * The functions below are written from X11R5 MIT's code (XImUtil.c)
1020 * The idea is to have faster functions than the standard XPutPixel function
1021 * to build the image data. Indeed we can speed up things by suppressing tests
1022 * performed for each pixel. We do the same tests but at the image level.
1023 * We also assume that we use only ZPixmap images with null offsets.
1026 LFUNC(_putbits, void, (register char *src, int dstoffset,
1027 register int numbits, register char *dst));
1029 LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
1031 static unsigned char const _reverse_byte[0x100] = {
1032 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1033 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1034 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1035 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1036 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1037 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1038 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1039 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1040 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1041 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1042 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1043 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1044 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1045 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1046 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1047 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1048 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1049 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1050 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1051 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1052 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1053 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1054 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1055 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1056 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1057 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1058 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1059 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1060 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1061 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1062 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1063 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1068 register unsigned char *bpt,
1069 register unsigned int nb)
1072 *bpt = _reverse_byte[*bpt];
1074 } while (--nb > 0); /* is nb user-controled? */
1080 xpm_xynormalizeimagebits(
1081 register unsigned char *bp,
1082 register XImage *img)
1084 register unsigned char c;
1086 if (img->byte_order != img->bitmap_bit_order) {
1087 switch (img->bitmap_unit) {
1100 *(bp + 2) = *(bp + 1);
1105 if (img->bitmap_bit_order == MSBFirst)
1106 _XReverse_Bytes(bp, img->bitmap_unit >> 3);
1110 xpm_znormalizeimagebits(
1111 register unsigned char *bp,
1112 register XImage *img)
1114 register unsigned char c;
1116 switch (img->bits_per_pixel) {
1119 _XReverse_Bytes(bp, 1);
1123 *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1143 *(bp + 2) = *(bp + 1);
1149 static unsigned char const _lomask[0x09] = {
1150 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1151 static unsigned char const _himask[0x09] = {
1152 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1156 register char *src, /* address of source bit string */
1157 int dstoffset, /* bit offset into destination;
1159 register int numbits, /* number of bits to copy to
1161 register char *dst) /* address of destination bit string */
1163 register unsigned char chlo, chhi;
1166 dst = dst + (dstoffset >> 3);
1167 dstoffset = dstoffset & 7;
1168 hibits = 8 - dstoffset;
1169 chlo = *dst & _lomask[dstoffset];
1171 chhi = (*src << dstoffset) & _himask[dstoffset];
1172 if (numbits <= hibits) {
1173 chhi = chhi & _lomask[dstoffset + numbits];
1174 *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1179 numbits = numbits - hibits;
1180 chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1182 if (numbits <= dstoffset) {
1183 chlo = chlo & _lomask[numbits];
1184 *dst = (*dst & _himask[numbits]) | chlo;
1187 numbits = numbits - dstoffset;
1192 * Default method to write pixels into a Z image data structure.
1193 * The algorithm used is:
1195 * copy the destination bitmap_unit or Zpixel to temp
1196 * normalize temp if needed
1197 * copy the pixel bits into the temp
1198 * renormalize temp if needed
1199 * copy the temp back into the destination image data
1206 unsigned int height,
1207 unsigned int *pixelindex,
1212 register unsigned int *iptr;
1213 register unsigned int x, y;
1214 register char *data;
1216 int nbytes, depth, ibu, ibpp, i;
1220 depth = image->depth;
1222 ibu = image->bitmap_unit;
1223 for (y = 0; y < height; y++) /* how can we trust height */
1224 for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1225 pixel = pixels[*iptr];
1226 for (i = 0, px = pixel; i < sizeof(unsigned long);
1228 ((unsigned char *) &pixel)[i] = px;
1229 src = &data[XYINDEX(x, y, image)];
1233 for (i = nbytes; --i >= 0;)
1235 XYNORMALIZE(&px, image);
1236 _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1237 XYNORMALIZE(&px, image);
1239 dst = &data[XYINDEX(x, y, image)];
1240 for (i = nbytes; --i >= 0;)
1244 ibpp = image->bits_per_pixel;
1245 for (y = 0; y < height; y++)
1246 for (x = 0; x < width; x++, iptr++) {
1247 pixel = pixels[*iptr];
1250 for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1252 ((unsigned char *) &pixel)[i] = px;
1253 src = &data[ZINDEX(x, y, image)];
1256 nbytes = (ibpp + 7) >> 3;
1257 for (i = nbytes; --i >= 0;)
1259 ZNORMALIZE(&px, image);
1260 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1261 ZNORMALIZE(&px, image);
1263 dst = &data[ZINDEX(x, y, image)];
1264 for (i = nbytes; --i >= 0;)
1271 * write pixels into a 32-bits Z image data structure
1274 #if !defined(WORD64) && !defined(LONG64)
1275 /* this item is static but deterministic so let it slide; doesn't
1276 * hurt re-entrancy of this library. Note if it is actually const then would
1277 * be OK under rules of ANSI-C but probably not C++ which may not
1278 * want to allocate space for it.
1280 static unsigned long byteorderpixel = MSBFirst << 24;
1285 WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1286 3.2e code - by default you get the speeded-up version.
1293 unsigned int height,
1294 unsigned int *pixelindex,
1297 unsigned char *data;
1302 #ifdef WITHOUT_SPEEDUPS
1305 unsigned char *addr;
1307 data = (unsigned char *) image->data;
1309 #if !defined(WORD64) && !defined(LONG64)
1310 if (*((char *) &byteorderpixel) == image->byte_order) {
1311 for (y = 0; y < height; y++)
1312 for (x = 0; x < width; x++, iptr++) {
1313 addr = &data[ZINDEX32(x, y, image)];
1314 *((unsigned long *) addr) = pixels[*iptr];
1318 if (image->byte_order == MSBFirst)
1319 for (y = 0; y < height; y++)
1320 for (x = 0; x < width; x++, iptr++) {
1321 addr = &data[ZINDEX32(x, y, image)];
1322 pixel = pixels[*iptr];
1323 addr[0] = pixel >> 24;
1324 addr[1] = pixel >> 16;
1325 addr[2] = pixel >> 8;
1329 for (y = 0; y < height; y++)
1330 for (x = 0; x < width; x++, iptr++) {
1331 addr = &data[ZINDEX32(x, y, image)];
1332 pixel = pixels[*iptr];
1334 addr[1] = pixel >> 8;
1335 addr[2] = pixel >> 16;
1336 addr[3] = pixel >> 24;
1339 #else /* WITHOUT_SPEEDUPS */
1341 unsigned int bpl = image->bytes_per_line;
1342 unsigned char *data_ptr, *max_data;
1344 data = (unsigned char *) image->data;
1346 #if !defined(WORD64) && !defined(LONG64)
1347 if (*((char *) &byteorderpixel) == image->byte_order) {
1348 for (y = 0; y < height; y++) {
1350 max_data = data_ptr + (width << 2);
1352 while (data_ptr < max_data) {
1353 *((unsigned long *) data_ptr) = pixels[*(iptr++)];
1354 data_ptr += (1 << 2);
1360 if (image->byte_order == MSBFirst)
1361 for (y = 0; y < height; y++) {
1363 max_data = data_ptr + (width << 2);
1365 while (data_ptr < max_data) {
1366 pixel = pixels[*(iptr++)];
1368 *data_ptr++ = pixel >> 24;
1369 *data_ptr++ = pixel >> 16;
1370 *data_ptr++ = pixel >> 8;
1371 *data_ptr++ = pixel;
1377 for (y = 0; y < height; y++) {
1379 max_data = data_ptr + (width << 2);
1381 while (data_ptr < max_data) {
1382 pixel = pixels[*(iptr++)];
1384 *data_ptr++ = pixel;
1385 *data_ptr++ = pixel >> 8;
1386 *data_ptr++ = pixel >> 16;
1387 *data_ptr++ = pixel >> 24;
1392 #endif /* WITHOUT_SPEEDUPS */
1396 * write pixels into a 16-bits Z image data structure
1403 unsigned int height,
1404 unsigned int *pixelindex,
1407 unsigned char *data;
1411 #ifdef WITHOUT_SPEEDUPS
1414 unsigned char *addr;
1416 data = (unsigned char *) image->data;
1418 if (image->byte_order == MSBFirst)
1419 for (y = 0; y < height; y++)
1420 for (x = 0; x < width; x++, iptr++) {
1421 addr = &data[ZINDEX16(x, y, image)];
1422 addr[0] = pixels[*iptr] >> 8;
1423 addr[1] = pixels[*iptr];
1426 for (y = 0; y < height; y++)
1427 for (x = 0; x < width; x++, iptr++) {
1428 addr = &data[ZINDEX16(x, y, image)];
1429 addr[0] = pixels[*iptr];
1430 addr[1] = pixels[*iptr] >> 8;
1433 #else /* WITHOUT_SPEEDUPS */
1437 unsigned int bpl = image->bytes_per_line;
1438 unsigned char *data_ptr, *max_data;
1440 data = (unsigned char *) image->data;
1442 if (image->byte_order == MSBFirst)
1443 for (y = 0; y < height; y++) {
1445 max_data = data_ptr + (width << 1);
1447 while (data_ptr < max_data) {
1448 pixel = pixels[*(iptr++)];
1450 data_ptr[0] = pixel >> 8;
1451 data_ptr[1] = pixel;
1453 data_ptr += (1 << 1);
1458 for (y = 0; y < height; y++) {
1460 max_data = data_ptr + (width << 1);
1462 while (data_ptr < max_data) {
1463 pixel = pixels[*(iptr++)];
1465 data_ptr[0] = pixel;
1466 data_ptr[1] = pixel >> 8;
1468 data_ptr += (1 << 1);
1473 #endif /* WITHOUT_SPEEDUPS */
1477 * write pixels into a 8-bits Z image data structure
1484 unsigned int height,
1485 unsigned int *pixelindex,
1492 #ifdef WITHOUT_SPEEDUPS
1498 for (y = 0; y < height; y++)
1499 for (x = 0; x < width; x++, iptr++)
1500 data[ZINDEX8(x, y, image)] = pixels[*iptr];
1502 #else /* WITHOUT_SPEEDUPS */
1504 unsigned int bpl = image->bytes_per_line;
1505 char *data_ptr, *max_data;
1510 for (y = 0; y < height; y++) {
1512 max_data = data_ptr + width;
1514 while (data_ptr < max_data)
1515 *(data_ptr++) = pixels[*(iptr++)];
1520 #endif /* WITHOUT_SPEEDUPS */
1524 * write pixels into a 1-bit depth image data structure and **offset null**
1531 unsigned int height,
1532 unsigned int *pixelindex,
1535 if (image->byte_order != image->bitmap_bit_order)
1536 PutImagePixels(image, width, height, pixelindex, pixels);
1542 #ifdef WITHOUT_SPEEDUPS
1548 if (image->bitmap_bit_order == MSBFirst)
1549 for (y = 0; y < height; y++)
1550 for (x = 0; x < width; x++, iptr++) {
1551 if (pixels[*iptr] & 1)
1552 data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1554 data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1557 for (y = 0; y < height; y++)
1558 for (x = 0; x < width; x++, iptr++) {
1559 if (pixels[*iptr] & 1)
1560 data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1562 data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1565 #else /* WITHOUT_SPEEDUPS */
1568 char *data_ptr, *max_data;
1569 int bpl = image->bytes_per_line;
1578 if (image->bitmap_bit_order == MSBFirst)
1579 for (y = 0; y < height; y++) {
1581 max_data = data_ptr + width;
1582 while (data_ptr < max_data) {
1585 value = (value << 1) | (pixels[*(iptr++)] & 1);
1586 value = (value << 1) | (pixels[*(iptr++)] & 1);
1587 value = (value << 1) | (pixels[*(iptr++)] & 1);
1588 value = (value << 1) | (pixels[*(iptr++)] & 1);
1589 value = (value << 1) | (pixels[*(iptr++)] & 1);
1590 value = (value << 1) | (pixels[*(iptr++)] & 1);
1591 value = (value << 1) | (pixels[*(iptr++)] & 1);
1592 value = (value << 1) | (pixels[*(iptr++)] & 1);
1594 *(data_ptr++) = value;
1598 for (count = 0; count < diff; count++) {
1599 if (pixels[*(iptr++)] & 1)
1600 value |= (0x80 >> count);
1602 *(data_ptr) = value;
1607 for (y = 0; y < height; y++) {
1609 max_data = data_ptr + width;
1610 while (data_ptr < max_data) {
1614 value = (value << 1) | (pixels[*(--iptr)] & 1);
1615 value = (value << 1) | (pixels[*(--iptr)] & 1);
1616 value = (value << 1) | (pixels[*(--iptr)] & 1);
1617 value = (value << 1) | (pixels[*(--iptr)] & 1);
1618 value = (value << 1) | (pixels[*(--iptr)] & 1);
1619 value = (value << 1) | (pixels[*(--iptr)] & 1);
1620 value = (value << 1) | (pixels[*(--iptr)] & 1);
1621 value = (value << 1) | (pixels[*(--iptr)] & 1);
1624 *(data_ptr++) = value;
1628 for (count = 0; count < diff; count++) {
1629 if (pixels[*(iptr++)] & 1)
1630 value |= (1 << count);
1632 *(data_ptr) = value;
1637 #endif /* WITHOUT_SPEEDUPS */
1642 XpmCreatePixmapFromXpmImage(
1646 Pixmap *pixmap_return,
1647 Pixmap *shapemask_return,
1648 XpmAttributes *attributes)
1650 XImage *ximage, *shapeimage;
1653 /* initialize return values */
1656 if (shapemask_return)
1657 *shapemask_return = 0;
1659 /* create the ximages */
1660 ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1661 (pixmap_return ? &ximage : NULL),
1663 &shapeimage : NULL),
1665 if (ErrorStatus < 0)
1666 return (ErrorStatus);
1668 /* create the pixmaps and destroy images */
1669 if (pixmap_return && ximage) {
1670 xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1671 XDestroyImage(ximage);
1673 if (shapemask_return && shapeimage) {
1674 xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1675 XDestroyImage(shapeimage);
1677 return (ErrorStatus);
1686 unsigned int height,
1687 unsigned int *pixelindex,
1690 unsigned int *data = pixelindex;
1692 unsigned char *array;
1694 BOOL success = FALSE;
1696 array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
1699 tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
1700 image->rp->BitMap->Depth);
1701 if (tmp_img != NULL)
1703 for (y = 0; y < height; ++y)
1705 for (x = 0; x < width; ++x)
1706 array[x] = pixels[*(data++)];
1707 WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
1709 FreeXImage (tmp_img);
1717 for (y = 0; y < height; ++y)
1718 for (x = 0; x < width; ++x)
1719 XPutPixel (image, x, y, pixels[*(data++)]);
1724 #else /* FOR_MSW part follows */
1730 unsigned int height,
1731 unsigned int *pixelindex,
1734 unsigned int *data = pixelindex;
1738 obm = SelectObject(*dc, image->bitmap);
1739 for (y = 0; y < height; y++) {
1740 for (x = 0; x < width; x++) {
1741 SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1744 SelectObject(*dc, obm);
1747 #endif /* FOR_MSW */
1751 #if !defined(FOR_MSW) && !defined(AMIGA)
1755 register XImage *ximage,
1758 unsigned long pixel)
1769 for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1770 ((unsigned char *)&pixel)[i] = px;
1771 src = &ximage->data[XYINDEX(x, y, ximage)];
1774 nbytes = ximage->bitmap_unit >> 3;
1775 for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1776 XYNORMALIZE(&px, ximage);
1777 i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1778 _putbits ((char *)&pixel, i, 1, (char *)&px);
1779 XYNORMALIZE(&px, ximage);
1781 dst = &ximage->data[XYINDEX(x, y, ximage)];
1782 for (i = nbytes; --i >= 0; )
1790 register XImage *ximage,
1793 unsigned long pixel)
1799 unsigned int nbytes, ibpp;
1804 ibpp = ximage->bits_per_pixel;
1805 if (ximage->depth == 4)
1807 for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1808 ((unsigned char *) &pixel)[i] = px;
1809 src = &ximage->data[ZINDEX(x, y, ximage)];
1812 nbytes = (ibpp + 7) >> 3;
1813 for (i = nbytes; --i >= 0;)
1815 ZNORMALIZE(&px, ximage);
1816 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1817 ZNORMALIZE(&px, ximage);
1819 dst = &ximage->data[ZINDEX(x, y, ximage)];
1820 for (i = nbytes; --i >= 0;)
1826 #if !defined(WORD64) && !defined(LONG64)
1829 register XImage *ximage,
1832 unsigned long pixel)
1834 unsigned char *addr;
1839 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1840 *((unsigned long *)addr) = pixel;
1847 register XImage *ximage,
1850 unsigned long pixel)
1852 unsigned char *addr;
1857 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1858 addr[0] = pixel >> 24;
1859 addr[1] = pixel >> 16;
1860 addr[2] = pixel >> 8;
1867 register XImage *ximage,
1870 unsigned long pixel)
1872 unsigned char *addr;
1877 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1878 addr[3] = pixel >> 24;
1879 addr[2] = pixel >> 16;
1880 addr[1] = pixel >> 8;
1887 register XImage *ximage,
1890 unsigned long pixel)
1892 unsigned char *addr;
1897 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1898 addr[0] = pixel >> 8;
1905 register XImage *ximage,
1908 unsigned long pixel)
1910 unsigned char *addr;
1915 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1916 addr[1] = pixel >> 8;
1923 register XImage *ximage,
1926 unsigned long pixel)
1931 ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1937 register XImage *ximage,
1940 unsigned long pixel)
1946 ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1948 ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1954 register XImage *ximage,
1957 unsigned long pixel)
1963 ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1965 ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1969 #endif /* not FOR_MSW && not AMIGA */
1972 * This function parses an Xpm file or data and directly create an XImage
1975 xpmParseDataAndCreate(
1978 XImage **image_return,
1979 XImage **shapeimage_return,
1982 XpmAttributes *attributes)
1984 /* variables stored in the XpmAttributes structure */
1989 XpmFreeColorsFunc freeColors;
1991 /* variables to return */
1992 XImage *ximage = NULL;
1993 XImage *shapeimage = NULL;
1994 unsigned int mask_pixel_index = XpmUndefPixel;
1996 /* calculation variables */
1997 Pixel *image_pixels = NULL;
1998 Pixel *mask_pixels = NULL;
1999 Pixel *alloc_pixels = NULL;
2000 Pixel *used_pixels = NULL;
2001 unsigned int nalloc_pixels = 0;
2002 unsigned int nused_pixels = 0;
2003 unsigned int width, height, ncolors, cpp;
2004 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
2005 XpmColor *colorTable = NULL;
2006 char *hints_cmt = NULL;
2007 char *colors_cmt = NULL;
2008 char *pixels_cmt = NULL;
2012 xpmHashTable hashtable;
2015 /* initialize return values */
2017 *image_return = NULL;
2018 if (shapeimage_return)
2019 *shapeimage_return = NULL;
2022 /* retrieve information from the XpmAttributes */
2023 if (attributes && (attributes->valuemask & XpmVisual))
2024 visual = attributes->visual;
2026 visual = XDefaultVisual(display, XDefaultScreen(display));
2028 if (attributes && (attributes->valuemask & XpmColormap))
2029 colormap = attributes->colormap;
2031 colormap = XDefaultColormap(display, XDefaultScreen(display));
2033 if (attributes && (attributes->valuemask & XpmDepth))
2034 depth = attributes->depth;
2036 depth = XDefaultDepth(display, XDefaultScreen(display));
2038 if (attributes && (attributes->valuemask & XpmBitmapFormat))
2039 bitmap_format = attributes->bitmap_format;
2041 bitmap_format = ZPixmap;
2043 if (attributes && (attributes->valuemask & XpmFreeColors))
2044 freeColors = attributes->free_colors;
2046 freeColors = FreeColors;
2048 cmts = info && (info->valuemask & XpmReturnComments);
2053 ErrorStatus = xpmParseHeader(data);
2054 if (ErrorStatus != XpmSuccess)
2055 return (ErrorStatus);
2060 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2061 &x_hotspot, &y_hotspot, &hotspot,
2063 if (ErrorStatus != XpmSuccess)
2064 return (ErrorStatus);
2067 * store the hints comment line
2070 xpmGetCmt(data, &hints_cmt);
2073 * init the hashtable
2075 if (USE_HASHTABLE) {
2076 ErrorStatus = xpmHashTableInit(&hashtable);
2077 if (ErrorStatus != XpmSuccess)
2078 RETURN(ErrorStatus);
2084 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2085 if (ErrorStatus != XpmSuccess)
2086 RETURN(ErrorStatus);
2089 * store the colors comment line
2092 xpmGetCmt(data, &colors_cmt);
2094 /* malloc pixels index tables */
2095 if (ncolors >= UINT_MAX / sizeof(Pixel))
2096 RETURN(XpmNoMemory);
2098 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2100 RETURN(XpmNoMemory);
2102 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2104 RETURN(XpmNoMemory);
2106 /* maximum of allocated pixels will be the number of colors */
2107 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2109 RETURN(XpmNoMemory);
2111 /* maximum of allocated pixels will be the number of colors */
2112 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2114 RETURN(XpmNoMemory);
2116 /* get pixel colors, store them in index tables */
2117 ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2118 image_pixels, mask_pixels, &mask_pixel_index,
2119 alloc_pixels, &nalloc_pixels, used_pixels,
2122 if (ErrorStatus != XpmSuccess
2123 && (ErrorStatus < 0 || (attributes
2124 && (attributes->valuemask & XpmExactColors)
2125 && attributes->exactColors)))
2126 RETURN(ErrorStatus);
2128 /* now create the ximage */
2130 ErrorStatus = CreateXImage(display, visual, depth,
2131 (depth == 1 ? bitmap_format : ZPixmap),
2132 width, height, &ximage);
2133 if (ErrorStatus != XpmSuccess)
2134 RETURN(ErrorStatus);
2136 #if !defined(FOR_MSW) && !defined(AMIGA)
2139 * set the XImage pointer function, to be used with XPutPixel,
2140 * to an internal optimized function
2143 if (ximage->bits_per_pixel == 8)
2144 ximage->f.put_pixel = PutPixel8;
2145 else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2146 (ximage->byte_order == ximage->bitmap_bit_order))
2147 if (ximage->bitmap_bit_order == MSBFirst)
2148 ximage->f.put_pixel = PutPixel1MSB;
2150 ximage->f.put_pixel = PutPixel1LSB;
2151 else if (ximage->bits_per_pixel == 16)
2152 if (ximage->bitmap_bit_order == MSBFirst)
2153 ximage->f.put_pixel = PutPixel16MSB;
2155 ximage->f.put_pixel = PutPixel16LSB;
2156 else if (ximage->bits_per_pixel == 32)
2157 #if !defined(WORD64) && !defined(LONG64)
2158 if (*((char *)&byteorderpixel) == ximage->byte_order)
2159 ximage->f.put_pixel = PutPixel32;
2162 if (ximage->bitmap_bit_order == MSBFirst)
2163 ximage->f.put_pixel = PutPixel32MSB;
2165 ximage->f.put_pixel = PutPixel32LSB;
2166 else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2167 ximage->f.put_pixel = PutPixel1;
2169 ximage->f.put_pixel = PutPixel;
2170 #endif /* not FOR_MSW && not AMIGA */
2173 /* create the shape mask image */
2174 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2175 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2176 width, height, &shapeimage);
2177 if (ErrorStatus != XpmSuccess)
2178 RETURN(ErrorStatus);
2180 #if !defined(FOR_MSW) && !defined(AMIGA)
2181 if (shapeimage->bitmap_bit_order == MSBFirst)
2182 shapeimage->f.put_pixel = PutPixel1MSB;
2184 shapeimage->f.put_pixel = PutPixel1LSB;
2189 * read pixels and put them in the XImage
2191 ErrorStatus = ParseAndPutPixels(
2195 data, width, height, ncolors, cpp,
2196 colorTable, &hashtable,
2197 ximage, image_pixels,
2198 shapeimage, mask_pixels);
2199 XpmFree(image_pixels);
2200 image_pixels = NULL;
2201 XpmFree(mask_pixels);
2207 if (ErrorStatus != XpmSuccess)
2208 RETURN(ErrorStatus);
2209 else if (USE_HASHTABLE)
2210 xpmHashTableFree(&hashtable);
2213 * store the pixels comment line
2216 xpmGetCmt(data, &pixels_cmt);
2221 if (info && (info->valuemask & XpmReturnExtensions)) {
2223 ErrorStatus = xpmParseExtensions(data, &info->extensions,
2224 &info->nextensions);
2225 if (ErrorStatus != XpmSuccess)
2226 RETURN(ErrorStatus);
2228 info->extensions = NULL;
2229 info->nextensions = 0;
2233 * store found informations in the XpmImage structure
2235 image->width = width;
2236 image->height = height;
2238 image->ncolors = ncolors;
2239 image->colorTable = colorTable;
2244 info->hints_cmt = hints_cmt;
2245 info->colors_cmt = colors_cmt;
2246 info->pixels_cmt = pixels_cmt;
2249 info->x_hotspot = x_hotspot;
2250 info->y_hotspot = y_hotspot;
2251 info->valuemask |= XpmHotspot;
2254 /* if requested return used pixels in the XpmAttributes structure */
2255 if (attributes && (attributes->valuemask & XpmReturnPixels ||
2256 /* 3.2 backward compatibility code */
2257 attributes->valuemask & XpmReturnInfos)) {
2259 attributes->pixels = used_pixels;
2260 attributes->npixels = nused_pixels;
2261 attributes->mask_pixel = mask_pixel_index;
2263 XpmFree(used_pixels);
2265 /* if requested return alloc'ed pixels in the XpmAttributes structure */
2266 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2267 attributes->alloc_pixels = alloc_pixels;
2268 attributes->nalloc_pixels = nalloc_pixels;
2270 XpmFree(alloc_pixels);
2272 /* return created images */
2274 *image_return = ximage;
2275 if (shapeimage_return)
2276 *shapeimage_return = shapeimage;
2278 return (XpmSuccess);
2280 /* exit point in case of error, free only locally allocated variables */
2283 xpmHashTableFree(&hashtable);
2285 xpmFreeColorTable(colorTable, ncolors);
2289 XpmFree(colors_cmt);
2291 XpmFree(pixels_cmt);
2293 XDestroyImage(ximage);
2295 XDestroyImage(shapeimage);
2297 XpmFree(image_pixels);
2299 XpmFree(mask_pixels);
2301 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
2303 XpmFree(alloc_pixels);
2305 XpmFree(used_pixels);
2307 return (ErrorStatus);
2317 unsigned int height,
2318 unsigned int ncolors,
2320 XpmColor *colorTable,
2321 xpmHashTable *hashtable,
2323 Pixel *image_pixels,
2325 Pixel *shape_pixels)
2327 unsigned int a, x, y;
2331 case (1): /* Optimize for single character
2334 unsigned short colidx[256];
2340 shapedc = CreateCompatibleDC(*dc);
2341 sobm = SelectObject(shapedc, shapeimage->bitmap);
2345 obm = SelectObject(*dc, image->bitmap);
2348 return (XpmFileInvalid);
2350 bzero((char *)colidx, 256 * sizeof(short));
2351 for (a = 0; a < ncolors; a++)
2352 colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2354 for (y = 0; y < height; y++) {
2355 xpmNextString(data);
2356 for (x = 0; x < width; x++) {
2357 int c = xpmGetC(data);
2359 if (c > 0 && c < 256 && colidx[c] != 0) {
2361 XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2363 XPutPixel(shapeimage, x, y,
2364 shape_pixels[colidx[c] - 1]);
2366 SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2368 SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
2372 return (XpmFileInvalid);
2377 SelectObject(shapedc, sobm);
2380 SelectObject(*dc, obm);
2385 case (2): /* Optimize for double character
2389 /* free all allocated pointers at all exits */
2390 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2391 if (cidx[f]) XpmFree(cidx[f]);}
2393 /* array of pointers malloced by need */
2394 unsigned short *cidx[256];
2397 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2398 for (a = 0; a < ncolors; a++) {
2399 char1 = (unsigned char) colorTable[a].string[0];
2400 if (cidx[char1] == NULL) { /* get new memory */
2401 cidx[char1] = (unsigned short *)
2402 XpmCalloc(256, sizeof(unsigned short));
2403 if (cidx[char1] == NULL) { /* new block failed */
2405 return (XpmNoMemory);
2408 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2411 for (y = 0; y < height; y++) {
2412 xpmNextString(data);
2413 for (x = 0; x < width; x++) {
2414 int cc1 = xpmGetC(data);
2415 if (cc1 > 0 && cc1 < 256) {
2416 int cc2 = xpmGetC(data);
2417 if (cc2 > 0 && cc2 < 256 &&
2418 cidx[cc1] && cidx[cc1][cc2] != 0) {
2420 XPutPixel(image, x, y,
2421 image_pixels[cidx[cc1][cc2] - 1]);
2423 XPutPixel(shapeimage, x, y,
2424 shape_pixels[cidx[cc1][cc2] - 1]);
2426 SelectObject(*dc, image->bitmap);
2427 SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2429 SelectObject(*dc, shapeimage->bitmap);
2431 shape_pixels[cidx[cc1][cc2] - 1]);
2436 return (XpmFileInvalid);
2440 return (XpmFileInvalid);
2448 default: /* Non-optimized case of long color
2454 if (cpp >= sizeof(buf))
2455 return (XpmFileInvalid);
2458 if (USE_HASHTABLE) {
2461 for (y = 0; y < height; y++) {
2462 xpmNextString(data);
2463 for (x = 0; x < width; x++) {
2464 for (a = 0, s = buf; a < cpp; a++, s++)
2466 slot = xpmHashSlot(hashtable, buf);
2467 if (!*slot) /* no color matches */
2468 return (XpmFileInvalid);
2470 XPutPixel(image, x, y,
2471 image_pixels[HashColorIndex(slot)]);
2473 XPutPixel(shapeimage, x, y,
2474 shape_pixels[HashColorIndex(slot)]);
2476 SelectObject(*dc, image->bitmap);
2478 image_pixels[HashColorIndex(slot)]);
2480 SelectObject(*dc, shapeimage->bitmap);
2482 shape_pixels[HashColorIndex(slot)]);
2488 for (y = 0; y < height; y++) {
2489 xpmNextString(data);
2490 for (x = 0; x < width; x++) {
2491 for (a = 0, s = buf; a < cpp; a++, s++)
2493 for (a = 0; a < ncolors; a++)
2494 if (!strcmp(colorTable[a].string, buf))
2496 if (a == ncolors) /* no color matches */
2497 return (XpmFileInvalid);
2499 XPutPixel(image, x, y, image_pixels[a]);
2501 XPutPixel(shapeimage, x, y, shape_pixels[a]);
2503 SelectObject(*dc, image->bitmap);
2504 SetPixel(*dc, x, y, image_pixels[a]);
2506 SelectObject(*dc, shapeimage->bitmap);
2507 SetPixel(*dc, x, y, shape_pixels[a]);
2516 return (XpmSuccess);