diff options
Diffstat (limited to 'libXpm/src/create.c')
-rw-r--r-- | libXpm/src/create.c | 5034 |
1 files changed, 2517 insertions, 2517 deletions
diff --git a/libXpm/src/create.c b/libXpm/src/create.c index 7c75a4211..f9823ca6c 100644 --- a/libXpm/src/create.c +++ b/libXpm/src/create.c @@ -1,2517 +1,2517 @@ -/* - * Copyright (C) 1989-95 GROUPE BULL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of GROUPE BULL shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from GROUPE BULL. - */ - -/*****************************************************************************\ -* create.c: * -* * -* XPM library * -* Create an X image and possibly its related shape mask * -* from the given XpmImage. * -* * -* Developed by Arnaud Le Hors * -\*****************************************************************************/ - -/* - * The code related to FOR_MSW has been added by - * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 - */ - -/* - * The code related to AMIGA has been added by - * Lorens Younes (d93-hyo@nada.kth.se) 4/96 - */ - -/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "XpmI.h" -#include <ctype.h> - -LFUNC(xpmVisualType, int, (Visual *visual)); - -LFUNC(AllocColor, int, (Display *display, Colormap colormap, - char *colorname, XColor *xcolor, void *closure)); -LFUNC(FreeColors, int, (Display *display, Colormap colormap, - Pixel *pixels, int n, void *closure)); - -#ifndef FOR_MSW -LFUNC(SetCloseColor, int, (Display *display, Colormap colormap, - Visual *visual, XColor *col, - Pixel *image_pixel, Pixel *mask_pixel, - Pixel *alloc_pixels, unsigned int *nalloc_pixels, - XpmAttributes *attributes, XColor *cols, int ncols, - XpmAllocColorFunc allocColor, void *closure)); -#else -/* let the window system take care of close colors */ -#endif - -LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual, - char *colorname, unsigned int color_index, - Pixel *image_pixel, Pixel *mask_pixel, - unsigned int *mask_pixel_index, - Pixel *alloc_pixels, unsigned int *nalloc_pixels, - Pixel *used_pixels, unsigned int *nused_pixels, - XpmAttributes *attributes, XColor *cols, int ncols, - XpmAllocColorFunc allocColor, void *closure)); - -LFUNC(CreateXImage, int, (Display *display, Visual *visual, - unsigned int depth, int format, unsigned int width, - unsigned int height, XImage **image_return)); - -LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes, - XpmColor *colors, unsigned int ncolors, - Pixel *image_pixels, Pixel *mask_pixels, - unsigned int *mask_pixel_index, - Pixel *alloc_pixels, unsigned int *nalloc_pixels, - Pixel *used_pixels, unsigned int *nused_pixels)); - -#ifndef FOR_MSW -LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width, - unsigned int height, unsigned int ncolors, - unsigned int cpp, XpmColor *colorTable, - xpmHashTable *hashtable, - XImage *image, Pixel *image_pixels, - XImage *mask, Pixel *mask_pixels)); -#else /* FOR_MSW */ -LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width, - unsigned int height, unsigned int ncolors, - unsigned int cpp, XpmColor *colorTable, - xpmHashTable *hashtable, - XImage *image, Pixel *image_pixels, - XImage *mask, Pixel *mask_pixels)); -#endif - -#ifndef FOR_MSW -# ifndef AMIGA -/* XImage pixel routines */ -LFUNC(PutImagePixels, void, (XImage *image, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); - -LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); - -LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); - -LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); - -LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); - -LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel)); -#if !defined(WORD64) && !defined(LONG64) -LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel)); -#endif -LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); -LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); - -# else /* AMIGA */ -LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width, - unsigned int height, unsigned int *pixelindex, - Pixel *pixels)); -# endif/* AMIGA */ -#else /* FOR_MSW */ -/* FOR_MSW pixel routine */ -LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image, - unsigned int width, unsigned int height, - unsigned int *pixelindex, Pixel *pixels)); -#endif /* FOR_MSW */ - -#ifdef NEED_STRCASECMP -FUNC(xpmstrcasecmp, int, (char *s1, char *s2)); - -/* - * in case strcasecmp is not provided by the system here is one - * which does the trick - */ -int -xpmstrcasecmp( - register char *s1, - register char *s2) -{ - register int c1, c2; - - while (*s1 && *s2) { - c1 = tolower(*s1); - c2 = tolower(*s2); - if (c1 != c2) - return (c1 - c2); - s1++; - s2++; - } - return (int) (*s1 - *s2); -} - -#endif - -/* - * return the default color key related to the given visual - */ -static int -xpmVisualType(Visual *visual) -{ -#ifndef FOR_MSW -# ifndef AMIGA - switch (visual->class) { - case StaticGray: - case GrayScale: - switch (visual->map_entries) { - case 2: - return (XPM_MONO); - case 4: - return (XPM_GRAY4); - default: - return (XPM_GRAY); - } - default: - return (XPM_COLOR); - } -# else - /* set the key explicitly in the XpmAttributes to override this */ - return (XPM_COLOR); -# endif -#else - /* there should be a similar switch for MSW */ - return (XPM_COLOR); -#endif -} - - -typedef struct { - int cols_index; - long closeness; -} CloseColor; - -static int -closeness_cmp(Const void *a, Const void *b) -{ - CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b; - - /* cast to int as qsort requires */ - return (int) (x->closeness - y->closeness); -} - - -/* default AllocColor function: - * call XParseColor if colorname is given, return negative value if failure - * call XAllocColor and return 0 if failure, positive otherwise - */ -static int -AllocColor( - Display *display, - Colormap colormap, - char *colorname, - XColor *xcolor, - void *closure) /* not used */ -{ - int status; - if (colorname) - if (!XParseColor(display, colormap, colorname, xcolor)) - return -1; - status = XAllocColor(display, colormap, xcolor); - return status != 0 ? 1 : 0; -} - - -#ifndef FOR_MSW -/* - * set a close color in case the exact one can't be set - * return 0 if success, 1 otherwise. - */ - -static int -SetCloseColor( - Display *display, - Colormap colormap, - Visual *visual, - XColor *col, - Pixel *image_pixel, - Pixel *mask_pixel, - Pixel *alloc_pixels, - unsigned int *nalloc_pixels, - XpmAttributes *attributes, - XColor *cols, - int ncols, - XpmAllocColorFunc allocColor, - void *closure) -{ - - /* - * Allocation failed, so try close colors. To get here the visual must - * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor? - * What about sharing systems like QDSS?). Beware: we have to treat - * DirectColor differently. - */ - - - long int red_closeness, green_closeness, blue_closeness; - int n; - Bool alloc_color; - - if (attributes && (attributes->valuemask & XpmCloseness)) - red_closeness = green_closeness = blue_closeness = - attributes->closeness; - else { - red_closeness = attributes->red_closeness; - green_closeness = attributes->green_closeness; - blue_closeness = attributes->blue_closeness; - } - if (attributes && (attributes->valuemask & XpmAllocCloseColors)) - alloc_color = attributes->alloc_close_colors; - else - alloc_color = True; - - /* - * We sort the colormap by closeness and try to allocate the color - * closest to the target. If the allocation of this close color fails, - * which almost never happens, then one of two scenarios is possible. - * Either the colormap must have changed (since the last close color - * allocation or possibly while we were sorting the colormap), or the - * color is allocated as Read/Write by some other client. (Note: X - * _should_ allow clients to check if a particular color is Read/Write, - * but it doesn't! :-( ). We cannot determine which of these scenarios - * occurred, so we try the next closest color, and so on, until no more - * colors are within closeness of the target. If we knew that the - * colormap had changed, we could skip this sequence. - * - * If _none_ of the colors within closeness of the target can be allocated, - * then we can finally be pretty sure that the colormap has actually - * changed. In this case we try to allocate the original color (again), - * then try the closecolor stuff (again)... - * - * In theory it would be possible for an infinite loop to occur if another - * process kept changing the colormap every time we sorted it, so we set - * a maximum on the number of iterations. After this many tries, we use - * XGrabServer() to ensure that the colormap remains unchanged. - * - * This approach gives particularly bad worst case performance - as many as - * <MaximumIterations> colormap reads and sorts may be needed, and as - * many as <MaximumIterations> * <ColormapSize> attempted allocations - * may fail. On an 8-bit system, this means as many as 3 colormap reads, - * 3 sorts and 768 failed allocations per execution of this code! - * Luckily, my experiments show that in general use in a typical 8-bit - * color environment only about 1 in every 10000 allocations fails to - * succeed in the fastest possible time. So virtually every time what - * actually happens is a single sort followed by a successful allocate. - * The very first allocation also costs a colormap read, but no further - * reads are usually necessary. - */ - -#define ITERATIONS 2 /* more than one is almost never - * necessary */ - - for (n = 0; n <= ITERATIONS; ++n) { - CloseColor *closenesses = - (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor)); - int i, c; - - for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */ -#define COLOR_FACTOR 3 -#define BRIGHTNESS_FACTOR 1 - - closenesses[i].cols_index = i; - closenesses[i].closeness = - COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red) - + abs((long) col->green - (long) cols[i].green) - + abs((long) col->blue - (long) cols[i].blue)) - + BRIGHTNESS_FACTOR * abs(((long) col->red + - (long) col->green + - (long) col->blue) - - ((long) cols[i].red + - (long) cols[i].green + - (long) cols[i].blue)); - } - qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp); - - i = 0; - c = closenesses[i].cols_index; - while ((long) cols[c].red >= (long) col->red - red_closeness && - (long) cols[c].red <= (long) col->red + red_closeness && - (long) cols[c].green >= (long) col->green - green_closeness && - (long) cols[c].green <= (long) col->green + green_closeness && - (long) cols[c].blue >= (long) col->blue - blue_closeness && - (long) cols[c].blue <= (long) col->blue + blue_closeness) { - if (alloc_color) { - if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){ - if (n == ITERATIONS) - XUngrabServer(display); - XpmFree(closenesses); - *image_pixel = cols[c].pixel; - *mask_pixel = 1; - alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel; - return (0); - } else { - ++i; - if (i == ncols) - break; - c = closenesses[i].cols_index; - } - } else { - if (n == ITERATIONS) - XUngrabServer(display); - XpmFree(closenesses); - *image_pixel = cols[c].pixel; - *mask_pixel = 1; - return (0); - } - } - - /* Couldn't allocate _any_ of the close colors! */ - - if (n == ITERATIONS) - XUngrabServer(display); - XpmFree(closenesses); - - if (i == 0 || i == ncols) /* no color close enough or cannot */ - return (1); /* alloc any color (full of r/w's) */ - - if ((*allocColor)(display, colormap, NULL, col, closure)) { - *image_pixel = col->pixel; - *mask_pixel = 1; - alloc_pixels[(*nalloc_pixels)++] = col->pixel; - return (0); - } else { /* colormap has probably changed, so - * re-read... */ - if (n == ITERATIONS - 1) - XGrabServer(display); - -#if 0 - if (visual->class == DirectColor) { - /* TODO */ - } else -#endif - XQueryColors(display, colormap, cols, ncols); - } - } - return (1); -} - -#define USE_CLOSECOLOR attributes && \ -(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \ - || ((attributes->valuemask & XpmRGBCloseness) && \ - (attributes->red_closeness != 0 \ - || attributes->green_closeness != 0 \ - || attributes->blue_closeness != 0))) - -#else - /* FOR_MSW part */ - /* nothing to do here, the window system does it */ -#endif - -/* - * set the color pixel related to the given colorname, - * return 0 if success, 1 otherwise. - */ - -static int -SetColor( - Display *display, - Colormap colormap, - Visual *visual, - char *colorname, - unsigned int color_index, - Pixel *image_pixel, - Pixel *mask_pixel, - unsigned int *mask_pixel_index, - Pixel *alloc_pixels, - unsigned int *nalloc_pixels, - Pixel *used_pixels, - unsigned int *nused_pixels, - XpmAttributes *attributes, - XColor *cols, - int ncols, - XpmAllocColorFunc allocColor, - void *closure) -{ - XColor xcolor; - int status; - - if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) { - status = (*allocColor)(display, colormap, colorname, &xcolor, closure); - if (status < 0) /* parse color failed */ - return (1); - - if (status == 0) { -#ifndef FOR_MSW - if (USE_CLOSECOLOR) - return (SetCloseColor(display, colormap, visual, &xcolor, - image_pixel, mask_pixel, - alloc_pixels, nalloc_pixels, - attributes, cols, ncols, - allocColor, closure)); - else -#endif /* ndef FOR_MSW */ - return (1); - } else - alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel; - *image_pixel = xcolor.pixel; -#ifndef FOR_MSW - *mask_pixel = 1; -#else - *mask_pixel = RGB(0,0,0); -#endif - used_pixels[(*nused_pixels)++] = xcolor.pixel; - } else { - *image_pixel = 0; -#ifndef FOR_MSW - *mask_pixel = 0; -#else - *mask_pixel = RGB(255,255,255); -#endif - /* store the color table index */ - *mask_pixel_index = color_index; - } - return (0); -} - - -static int -CreateColors( - Display *display, - XpmAttributes *attributes, - XpmColor *colors, - unsigned int ncolors, - Pixel *image_pixels, - Pixel *mask_pixels, - unsigned int *mask_pixel_index, - Pixel *alloc_pixels, - unsigned int *nalloc_pixels, - Pixel *used_pixels, - unsigned int *nused_pixels) -{ - /* variables stored in the XpmAttributes structure */ - Visual *visual; - Colormap colormap; - XpmColorSymbol *colorsymbols = NULL; - unsigned int numsymbols; - XpmAllocColorFunc allocColor; - void *closure; - - char *colorname; - unsigned int color, key; - Bool pixel_defined; - XpmColorSymbol *symbol = NULL; - char **defaults; - int ErrorStatus = XpmSuccess; - char *s; - int default_index; - - XColor *cols = NULL; - unsigned int ncols = 0; - - /* - * retrieve information from the XpmAttributes - */ - if (attributes && attributes->valuemask & XpmColorSymbols) { - colorsymbols = attributes->colorsymbols; - numsymbols = attributes->numsymbols; - } else - numsymbols = 0; - - if (attributes && attributes->valuemask & XpmVisual) - visual = attributes->visual; - else - visual = XDefaultVisual(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmColormap)) - colormap = attributes->colormap; - else - colormap = XDefaultColormap(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmColorKey)) - key = attributes->color_key; - else - key = xpmVisualType(visual); - - if (attributes && (attributes->valuemask & XpmAllocColor)) - allocColor = attributes->alloc_color; - else - allocColor = AllocColor; - if (attributes && (attributes->valuemask & XpmColorClosure)) - closure = attributes->color_closure; - else - closure = NULL; - -#ifndef FOR_MSW - if (USE_CLOSECOLOR) { - /* originally from SetCloseColor */ -#if 0 - if (visual->class == DirectColor) { - - /* - * TODO: Implement close colors for DirectColor visuals. This is - * difficult situation. Chances are that we will never get here, - * because any machine that supports DirectColor will probably - * also support TrueColor (and probably PseudoColor). Also, - * DirectColor colormaps can be very large, so looking for close - * colors may be too slow. - */ - } else { -#endif - unsigned int i; - -#ifndef AMIGA - ncols = visual->map_entries; -#else - ncols = colormap->Count; -#endif - cols = (XColor *) XpmCalloc(ncols, sizeof(XColor)); - for (i = 0; i < ncols; ++i) - cols[i].pixel = i; - XQueryColors(display, colormap, cols, ncols); -#if 0 - } -#endif - } -#endif /* ndef FOR_MSW */ - - switch (key) { - case XPM_MONO: - default_index = 2; - break; - case XPM_GRAY4: - default_index = 3; - break; - case XPM_GRAY: - default_index = 4; - break; - case XPM_COLOR: - default: - default_index = 5; - break; - } - - for (color = 0; color < ncolors; color++, colors++, - image_pixels++, mask_pixels++) { - colorname = NULL; - pixel_defined = False; - defaults = (char **) colors; - - /* - * look for a defined symbol - */ - if (numsymbols) { - - unsigned int n; - - s = defaults[1]; - for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) { - if (symbol->name && s && !strcmp(symbol->name, s)) - /* override name */ - break; - if (!symbol->name && symbol->value) { /* override value */ - int def_index = default_index; - - while (defaults[def_index] == NULL) /* find defined - * colorname */ - --def_index; - if (def_index < 2) {/* nothing towards mono, so try - * towards color */ - def_index = default_index + 1; - while (def_index <= 5 && defaults[def_index] == NULL) - ++def_index; - } - if (def_index >= 2 && defaults[def_index] != NULL && - !xpmstrcasecmp(symbol->value, defaults[def_index])) - break; - } - } - if (n != numsymbols) { - if (symbol->name && symbol->value) - colorname = symbol->value; - else - pixel_defined = True; - } - } - if (!pixel_defined) { /* pixel not given as symbol value */ - - unsigned int k; - - if (colorname) { /* colorname given as symbol value */ - if (!SetColor(display, colormap, visual, colorname, color, - image_pixels, mask_pixels, mask_pixel_index, - alloc_pixels, nalloc_pixels, used_pixels, - nused_pixels, attributes, cols, ncols, - allocColor, closure)) - pixel_defined = True; - else - ErrorStatus = XpmColorError; - } - k = key; - while (!pixel_defined && k > 1) { - if (defaults[k]) { - if (!SetColor(display, colormap, visual, defaults[k], - color, image_pixels, mask_pixels, - mask_pixel_index, alloc_pixels, - nalloc_pixels, used_pixels, nused_pixels, - attributes, cols, ncols, - allocColor, closure)) { - pixel_defined = True; - break; - } else - ErrorStatus = XpmColorError; - } - k--; - } - k = key + 1; - while (!pixel_defined && k < NKEYS + 1) { - if (defaults[k]) { - if (!SetColor(display, colormap, visual, defaults[k], - color, image_pixels, mask_pixels, - mask_pixel_index, alloc_pixels, - nalloc_pixels, used_pixels, nused_pixels, - attributes, cols, ncols, - allocColor, closure)) { - pixel_defined = True; - break; - } else - ErrorStatus = XpmColorError; - } - k++; - } - if (!pixel_defined) { - if (cols) - XpmFree(cols); - return (XpmColorFailed); - } - } else { - /* simply use the given pixel */ - *image_pixels = symbol->pixel; - /* the following makes the mask to be built even if none - is given a particular pixel */ - if (symbol->value - && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) { - *mask_pixels = 0; - *mask_pixel_index = color; - } else - *mask_pixels = 1; - used_pixels[(*nused_pixels)++] = *image_pixels; - } - } - if (cols) - XpmFree(cols); - return (ErrorStatus); -} - - -/* default FreeColors function, simply call XFreeColors */ -static int -FreeColors( - Display *display, - Colormap colormap, - Pixel *pixels, - int n, - void *closure) /* not used */ -{ - return XFreeColors(display, colormap, pixels, n, 0); -} - - -/* function call in case of error */ - -#undef RETURN -#define RETURN(status) \ -do \ -{ \ - ErrorStatus = status; \ - goto error; \ -} while(0) - -int -XpmCreateImageFromXpmImage( - Display *display, - XpmImage *image, - XImage **image_return, - XImage **shapeimage_return, - XpmAttributes *attributes) -{ - /* variables stored in the XpmAttributes structure */ - Visual *visual; - Colormap colormap; - unsigned int depth; - int bitmap_format; - XpmFreeColorsFunc freeColors; - - /* variables to return */ - XImage *ximage = NULL; - XImage *shapeimage = NULL; - unsigned int mask_pixel_index = XpmUndefPixel; - int ErrorStatus; - - /* calculation variables */ - Pixel *image_pixels = NULL; - Pixel *mask_pixels = NULL; - Pixel *alloc_pixels = NULL; - Pixel *used_pixels = NULL; - unsigned int nalloc_pixels = 0; - unsigned int nused_pixels = 0; - - /* initialize return values */ - if (image_return) - *image_return = NULL; - if (shapeimage_return) - *shapeimage_return = NULL; - - /* retrieve information from the XpmAttributes */ - if (attributes && (attributes->valuemask & XpmVisual)) - visual = attributes->visual; - else - visual = XDefaultVisual(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmColormap)) - colormap = attributes->colormap; - else - colormap = XDefaultColormap(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmDepth)) - depth = attributes->depth; - else - depth = XDefaultDepth(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmBitmapFormat)) - bitmap_format = attributes->bitmap_format; - else - bitmap_format = ZPixmap; - - if (attributes && (attributes->valuemask & XpmFreeColors)) - freeColors = attributes->free_colors; - else - freeColors = FreeColors; - - ErrorStatus = XpmSuccess; - - if (image->ncolors >= UINT_MAX / sizeof(Pixel)) - return (XpmNoMemory); - - /* malloc pixels index tables */ - image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); - if (!image_pixels) - return (XpmNoMemory); - - mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); - if (!mask_pixels) - RETURN(XpmNoMemory); - - /* maximum of allocated pixels will be the number of colors */ - alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); - if (!alloc_pixels) - RETURN(XpmNoMemory); - - /* maximum of allocated pixels will be the number of colors */ - used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); - if (!used_pixels) - RETURN(XpmNoMemory); - - /* get pixel colors, store them in index tables */ - ErrorStatus = CreateColors(display, attributes, image->colorTable, - image->ncolors, image_pixels, mask_pixels, - &mask_pixel_index, alloc_pixels, &nalloc_pixels, - used_pixels, &nused_pixels); - - if (ErrorStatus != XpmSuccess - && (ErrorStatus < 0 || (attributes - && (attributes->valuemask & XpmExactColors) - && attributes->exactColors))) - RETURN(ErrorStatus); - - /* create the ximage */ - if (image_return) { - ErrorStatus = CreateXImage(display, visual, depth, - (depth == 1 ? bitmap_format : ZPixmap), - image->width, image->height, &ximage); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - -#ifndef FOR_MSW -# ifndef AMIGA - - /* - * set the ximage data using optimized functions for ZPixmap - */ - - if (ximage->bits_per_pixel == 8) - PutImagePixels8(ximage, image->width, image->height, - image->data, image_pixels); - else if (((ximage->bits_per_pixel | ximage->depth) == 1) && - (ximage->byte_order == ximage->bitmap_bit_order)) - PutImagePixels1(ximage, image->width, image->height, - image->data, image_pixels); - else if (ximage->bits_per_pixel == 16) - PutImagePixels16(ximage, image->width, image->height, - image->data, image_pixels); - else if (ximage->bits_per_pixel == 32) - PutImagePixels32(ximage, image->width, image->height, - image->data, image_pixels); - else - PutImagePixels(ximage, image->width, image->height, - image->data, image_pixels); -# else /* AMIGA */ - APutImagePixels(ximage, image->width, image->height, - image->data, image_pixels); -# endif -#else /* FOR_MSW */ - MSWPutImagePixels(display, ximage, image->width, image->height, - image->data, image_pixels); -#endif - } - /* create the shape mask image */ - if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { - ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, - image->width, image->height, &shapeimage); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - -#ifndef FOR_MSW -# ifndef AMIGA - PutImagePixels1(shapeimage, image->width, image->height, - image->data, mask_pixels); -# else /* AMIGA */ - APutImagePixels(shapeimage, image->width, image->height, - image->data, mask_pixels); -# endif -#else /* FOR_MSW */ - MSWPutImagePixels(display, shapeimage, image->width, image->height, - image->data, mask_pixels); -#endif - - } - XpmFree(image_pixels); - XpmFree(mask_pixels); - - /* if requested return used pixels in the XpmAttributes structure */ - if (attributes && (attributes->valuemask & XpmReturnPixels || -/* 3.2 backward compatibility code */ - attributes->valuemask & XpmReturnInfos)) { -/* end 3.2 bc */ - attributes->pixels = used_pixels; - attributes->npixels = nused_pixels; - attributes->mask_pixel = mask_pixel_index; - } else - XpmFree(used_pixels); - - /* if requested return alloc'ed pixels in the XpmAttributes structure */ - if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { - attributes->alloc_pixels = alloc_pixels; - attributes->nalloc_pixels = nalloc_pixels; - } else - XpmFree(alloc_pixels); - - /* return created images */ - if (image_return) - *image_return = ximage; - if (shapeimage_return) - *shapeimage_return = shapeimage; - - return (ErrorStatus); - -/* exit point in case of error, free only locally allocated variables */ -error: - if (ximage) - XDestroyImage(ximage); - if (shapeimage) - XDestroyImage(shapeimage); - if (image_pixels) - XpmFree(image_pixels); - if (mask_pixels) - XpmFree(mask_pixels); - if (nalloc_pixels) - (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); - if (alloc_pixels) - XpmFree(alloc_pixels); - if (used_pixels) - XpmFree(used_pixels); - - return (ErrorStatus); -} - - -/* - * Create an XImage with its data - */ -static int -CreateXImage( - Display *display, - Visual *visual, - unsigned int depth, - int format, - unsigned int width, - unsigned int height, - XImage **image_return) -{ - int bitmap_pad; - - /* first get bitmap_pad */ - if (depth > 16) - bitmap_pad = 32; - else if (depth > 8) - bitmap_pad = 16; - else - bitmap_pad = 8; - - /* then create the XImage with data = NULL and bytes_per_line = 0 */ - *image_return = XCreateImage(display, visual, depth, format, 0, 0, - width, height, bitmap_pad, 0); - if (!*image_return) - return (XpmNoMemory); - -#if !defined(FOR_MSW) && !defined(AMIGA) - if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) { - XDestroyImage(*image_return); - return XpmNoMemory; - } - /* now that bytes_per_line must have been set properly alloc data */ - if((*image_return)->bytes_per_line == 0 || height == 0) - return XpmNoMemory; - (*image_return)->data = - (char *) XpmMalloc((*image_return)->bytes_per_line * height); - - if (!(*image_return)->data) { - XDestroyImage(*image_return); - *image_return = NULL; - return (XpmNoMemory); - } -#else - /* under FOR_MSW and AMIGA XCreateImage has done it all */ -#endif - return (XpmSuccess); -} - -#ifndef FOR_MSW -# ifndef AMIGA -/* - * The functions below are written from X11R5 MIT's code (XImUtil.c) - * - * The idea is to have faster functions than the standard XPutPixel function - * to build the image data. Indeed we can speed up things by suppressing tests - * performed for each pixel. We do the same tests but at the image level. - * We also assume that we use only ZPixmap images with null offsets. - */ - -LFUNC(_putbits, void, (register char *src, int dstoffset, - register int numbits, register char *dst)); - -LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb)); - -static unsigned char Const _reverse_byte[0x100] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; - -static int -_XReverse_Bytes( - register unsigned char *bpt, - register unsigned int nb) -{ - do { - *bpt = _reverse_byte[*bpt]; - bpt++; - } while (--nb > 0); /* is nb user-controled? */ - return 0; -} - - -void -xpm_xynormalizeimagebits( - register unsigned char *bp, - register XImage *img) -{ - register unsigned char c; - - if (img->byte_order != img->bitmap_bit_order) { - switch (img->bitmap_unit) { - - case 16: - c = *bp; - *bp = *(bp + 1); - *(bp + 1) = c; - break; - - case 32: - c = *(bp + 3); - *(bp + 3) = *bp; - *bp = c; - c = *(bp + 2); - *(bp + 2) = *(bp + 1); - *(bp + 1) = c; - break; - } - } - if (img->bitmap_bit_order == MSBFirst) - _XReverse_Bytes(bp, img->bitmap_unit >> 3); -} - -void -xpm_znormalizeimagebits( - register unsigned char *bp, - register XImage *img) -{ - register unsigned char c; - - switch (img->bits_per_pixel) { - - case 2: - _XReverse_Bytes(bp, 1); - break; - - case 4: - *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF); - break; - - case 16: - c = *bp; - *bp = *(bp + 1); - *(bp + 1) = c; - break; - - case 24: - c = *(bp + 2); - *(bp + 2) = *bp; - *bp = c; - break; - - case 32: - c = *(bp + 3); - *(bp + 3) = *bp; - *bp = c; - c = *(bp + 2); - *(bp + 2) = *(bp + 1); - *(bp + 1) = c; - break; - } -} - -static unsigned char Const _lomask[0x09] = { -0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; -static unsigned char Const _himask[0x09] = { -0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; - -static void -_putbits( - register char *src, /* address of source bit string */ - int dstoffset, /* bit offset into destination; - * range is 0-31 */ - register int numbits, /* number of bits to copy to - * destination */ - register char *dst) /* address of destination bit string */ -{ - register unsigned char chlo, chhi; - int hibits; - - dst = dst + (dstoffset >> 3); - dstoffset = dstoffset & 7; - hibits = 8 - dstoffset; - chlo = *dst & _lomask[dstoffset]; - for (;;) { - chhi = (*src << dstoffset) & _himask[dstoffset]; - if (numbits <= hibits) { - chhi = chhi & _lomask[dstoffset + numbits]; - *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi; - break; - } - *dst = chhi | chlo; - dst++; - numbits = numbits - hibits; - chlo = (unsigned char) (*src & _himask[hibits]) >> hibits; - src++; - if (numbits <= dstoffset) { - chlo = chlo & _lomask[numbits]; - *dst = (*dst & _himask[numbits]) | chlo; - break; - } - numbits = numbits - dstoffset; - } -} - -/* - * Default method to write pixels into a Z image data structure. - * The algorithm used is: - * - * copy the destination bitmap_unit or Zpixel to temp - * normalize temp if needed - * copy the pixel bits into the temp - * renormalize temp if needed - * copy the temp back into the destination image data - */ - -static void -PutImagePixels( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - register char *src; - register char *dst; - register unsigned int *iptr; - register unsigned int x, y; - register char *data; - Pixel pixel, px; - int nbytes, depth, ibu, ibpp, i; - - data = image->data; - iptr = pixelindex; - depth = image->depth; - if (depth == 1) { - ibu = image->bitmap_unit; - for (y = 0; y < height; y++) /* how can we trust height */ - for (x = 0; x < width; x++, iptr++) { /* how can we trust width */ - pixel = pixels[*iptr]; - for (i = 0, px = pixel; i < sizeof(unsigned long); - i++, px >>= 8) - ((unsigned char *) &pixel)[i] = px; - src = &data[XYINDEX(x, y, image)]; - dst = (char *) &px; - px = 0; - nbytes = ibu >> 3; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - XYNORMALIZE(&px, image); - _putbits((char *) &pixel, (x % ibu), 1, (char *) &px); - XYNORMALIZE(&px, image); - src = (char *) &px; - dst = &data[XYINDEX(x, y, image)]; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - } - } else { - ibpp = image->bits_per_pixel; - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - pixel = pixels[*iptr]; - if (depth == 4) - pixel &= 0xf; - for (i = 0, px = pixel; i < sizeof(unsigned long); i++, - px >>= 8) - ((unsigned char *) &pixel)[i] = px; - src = &data[ZINDEX(x, y, image)]; - dst = (char *) &px; - px = 0; - nbytes = (ibpp + 7) >> 3; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - ZNORMALIZE(&px, image); - _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); - ZNORMALIZE(&px, image); - src = (char *) &px; - dst = &data[ZINDEX(x, y, image)]; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - } - } -} - -/* - * write pixels into a 32-bits Z image data structure - */ - -#if !defined(WORD64) && !defined(LONG64) -/* this item is static but deterministic so let it slide; doesn't - * hurt re-entrancy of this library. Note if it is actually const then would - * be OK under rules of ANSI-C but probably not C++ which may not - * want to allocate space for it. - */ -static unsigned long byteorderpixel = MSBFirst << 24; - -#endif - -/* - WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original - 3.2e code - by default you get the speeded-up version. -*/ - -static void -PutImagePixels32( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - unsigned char *data; - unsigned int *iptr; - unsigned int y; - Pixel pixel; - -#ifdef WITHOUT_SPEEDUPS - - unsigned int x; - unsigned char *addr; - - data = (unsigned char *) image->data; - iptr = pixelindex; -#if !defined(WORD64) && !defined(LONG64) - if (*((char *) &byteorderpixel) == image->byte_order) { - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - addr = &data[ZINDEX32(x, y, image)]; - *((unsigned long *) addr) = pixels[*iptr]; - } - } else -#endif - if (image->byte_order == MSBFirst) - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - addr = &data[ZINDEX32(x, y, image)]; - pixel = pixels[*iptr]; - addr[0] = pixel >> 24; - addr[1] = pixel >> 16; - addr[2] = pixel >> 8; - addr[3] = pixel; - } - else - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - addr = &data[ZINDEX32(x, y, image)]; - pixel = pixels[*iptr]; - addr[0] = pixel; - addr[1] = pixel >> 8; - addr[2] = pixel >> 16; - addr[3] = pixel >> 24; - } - -#else /* WITHOUT_SPEEDUPS */ - - unsigned int bpl = image->bytes_per_line; - unsigned char *data_ptr, *max_data; - - data = (unsigned char *) image->data; - iptr = pixelindex; -#if !defined(WORD64) && !defined(LONG64) - if (*((char *) &byteorderpixel) == image->byte_order) { - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + (width << 2); - - while (data_ptr < max_data) { - *((unsigned long *) data_ptr) = pixels[*(iptr++)]; - data_ptr += (1 << 2); - } - data += bpl; - } - } else -#endif - if (image->byte_order == MSBFirst) - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + (width << 2); - - while (data_ptr < max_data) { - pixel = pixels[*(iptr++)]; - - *data_ptr++ = pixel >> 24; - *data_ptr++ = pixel >> 16; - *data_ptr++ = pixel >> 8; - *data_ptr++ = pixel; - - } - data += bpl; - } - else - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + (width << 2); - - while (data_ptr < max_data) { - pixel = pixels[*(iptr++)]; - - *data_ptr++ = pixel; - *data_ptr++ = pixel >> 8; - *data_ptr++ = pixel >> 16; - *data_ptr++ = pixel >> 24; - } - data += bpl; - } - -#endif /* WITHOUT_SPEEDUPS */ -} - -/* - * write pixels into a 16-bits Z image data structure - */ - -static void -PutImagePixels16( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - unsigned char *data; - unsigned int *iptr; - unsigned int y; - -#ifdef WITHOUT_SPEEDUPS - - unsigned int x; - unsigned char *addr; - - data = (unsigned char *) image->data; - iptr = pixelindex; - if (image->byte_order == MSBFirst) - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - addr = &data[ZINDEX16(x, y, image)]; - addr[0] = pixels[*iptr] >> 8; - addr[1] = pixels[*iptr]; - } - else - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - addr = &data[ZINDEX16(x, y, image)]; - addr[0] = pixels[*iptr]; - addr[1] = pixels[*iptr] >> 8; - } - -#else /* WITHOUT_SPEEDUPS */ - - Pixel pixel; - - unsigned int bpl = image->bytes_per_line; - unsigned char *data_ptr, *max_data; - - data = (unsigned char *) image->data; - iptr = pixelindex; - if (image->byte_order == MSBFirst) - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + (width << 1); - - while (data_ptr < max_data) { - pixel = pixels[*(iptr++)]; - - data_ptr[0] = pixel >> 8; - data_ptr[1] = pixel; - - data_ptr += (1 << 1); - } - data += bpl; - } - else - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + (width << 1); - - while (data_ptr < max_data) { - pixel = pixels[*(iptr++)]; - - data_ptr[0] = pixel; - data_ptr[1] = pixel >> 8; - - data_ptr += (1 << 1); - } - data += bpl; - } - -#endif /* WITHOUT_SPEEDUPS */ -} - -/* - * write pixels into a 8-bits Z image data structure - */ - -static void -PutImagePixels8( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - char *data; - unsigned int *iptr; - unsigned int y; - -#ifdef WITHOUT_SPEEDUPS - - unsigned int x; - - data = image->data; - iptr = pixelindex; - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) - data[ZINDEX8(x, y, image)] = pixels[*iptr]; - -#else /* WITHOUT_SPEEDUPS */ - - unsigned int bpl = image->bytes_per_line; - char *data_ptr, *max_data; - - data = image->data; - iptr = pixelindex; - - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + width; - - while (data_ptr < max_data) - *(data_ptr++) = pixels[*(iptr++)]; - - data += bpl; - } - -#endif /* WITHOUT_SPEEDUPS */ -} - -/* - * write pixels into a 1-bit depth image data structure and **offset null** - */ - -static void -PutImagePixels1( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - if (image->byte_order != image->bitmap_bit_order) - PutImagePixels(image, width, height, pixelindex, pixels); - else { - unsigned int *iptr; - unsigned int y; - char *data; - -#ifdef WITHOUT_SPEEDUPS - - unsigned int x; - - data = image->data; - iptr = pixelindex; - if (image->bitmap_bit_order == MSBFirst) - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - if (pixels[*iptr] & 1) - data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7); - else - data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7)); - } - else - for (y = 0; y < height; y++) - for (x = 0; x < width; x++, iptr++) { - if (pixels[*iptr] & 1) - data[ZINDEX1(x, y, image)] |= 1 << (x & 7); - else - data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7)); - } - -#else /* WITHOUT_SPEEDUPS */ - - char value; - char *data_ptr, *max_data; - int bpl = image->bytes_per_line; - int diff, count; - - data = image->data; - iptr = pixelindex; - - diff = width & 7; - width >>= 3; - - if (image->bitmap_bit_order == MSBFirst) - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + width; - while (data_ptr < max_data) { - value = 0; - - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - value = (value << 1) | (pixels[*(iptr++)] & 1); - - *(data_ptr++) = value; - } - if (diff) { - value = 0; - for (count = 0; count < diff; count++) { - if (pixels[*(iptr++)] & 1) - value |= (0x80 >> count); - } - *(data_ptr) = value; - } - data += bpl; - } - else - for (y = 0; y < height; y++) { - data_ptr = data; - max_data = data_ptr + width; - while (data_ptr < max_data) { - value = 0; - iptr += 8; - - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - value = (value << 1) | (pixels[*(--iptr)] & 1); - - iptr += 8; - *(data_ptr++) = value; - } - if (diff) { - value = 0; - for (count = 0; count < diff; count++) { - if (pixels[*(iptr++)] & 1) - value |= (1 << count); - } - *(data_ptr) = value; - } - data += bpl; - } - -#endif /* WITHOUT_SPEEDUPS */ - } -} - -int -XpmCreatePixmapFromXpmImage( - Display *display, - Drawable d, - XpmImage *image, - Pixmap *pixmap_return, - Pixmap *shapemask_return, - XpmAttributes *attributes) -{ - XImage *ximage, *shapeimage; - int ErrorStatus; - - /* initialize return values */ - if (pixmap_return) - *pixmap_return = 0; - if (shapemask_return) - *shapemask_return = 0; - - /* create the ximages */ - ErrorStatus = XpmCreateImageFromXpmImage(display, image, - (pixmap_return ? &ximage : NULL), - (shapemask_return ? - &shapeimage : NULL), - attributes); - if (ErrorStatus < 0) - return (ErrorStatus); - - /* create the pixmaps and destroy images */ - if (pixmap_return && ximage) { - xpmCreatePixmapFromImage(display, d, ximage, pixmap_return); - XDestroyImage(ximage); - } - if (shapemask_return && shapeimage) { - xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return); - XDestroyImage(shapeimage); - } - return (ErrorStatus); -} - -# else /* AMIGA */ - -static void -APutImagePixels ( - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - unsigned int *data = pixelindex; - unsigned int x, y; - unsigned char *array; - XImage *tmp_img; - BOOL success = FALSE; - - array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array)); - if (array != NULL) - { - tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, - image->rp->BitMap->Depth); - if (tmp_img != NULL) - { - for (y = 0; y < height; ++y) - { - for (x = 0; x < width; ++x) - array[x] = pixels[*(data++)]; - WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp); - } - FreeXImage (tmp_img); - success = TRUE; - } - XpmFree (array); - } - - if (!success) - { - for (y = 0; y < height; ++y) - for (x = 0; x < width; ++x) - XPutPixel (image, x, y, pixels[*(data++)]); - } -} - -# endif/* AMIGA */ -#else /* FOR_MSW part follows */ -static void -MSWPutImagePixels( - Display *dc, - XImage *image, - unsigned int width, - unsigned int height, - unsigned int *pixelindex, - Pixel *pixels) -{ - unsigned int *data = pixelindex; - unsigned int x, y; - HBITMAP obm; - - obm = SelectObject(*dc, image->bitmap); - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */ - } - } - SelectObject(*dc, obm); -} - -#endif /* FOR_MSW */ - - - -#if !defined(FOR_MSW) && !defined(AMIGA) - -static int -PutPixel1( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - register char *src; - register char *dst; - register int i; - Pixel px; - int nbytes; - - if(x < 0 || y < 0) - return 0; - - for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8) - ((unsigned char *)&pixel)[i] = px; - src = &ximage->data[XYINDEX(x, y, ximage)]; - dst = (char *)&px; - px = 0; - nbytes = ximage->bitmap_unit >> 3; - for (i = nbytes; --i >= 0; ) *dst++ = *src++; - XYNORMALIZE(&px, ximage); - i = ((x + ximage->xoffset) % ximage->bitmap_unit); - _putbits ((char *)&pixel, i, 1, (char *)&px); - XYNORMALIZE(&px, ximage); - src = (char *) &px; - dst = &ximage->data[XYINDEX(x, y, ximage)]; - for (i = nbytes; --i >= 0; ) - *dst++ = *src++; - - return 1; -} - -static int -PutPixel( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - register char *src; - register char *dst; - register int i; - Pixel px; - unsigned int nbytes, ibpp; - - if(x < 0 || y < 0) - return 0; - - ibpp = ximage->bits_per_pixel; - if (ximage->depth == 4) - pixel &= 0xf; - for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8) - ((unsigned char *) &pixel)[i] = px; - src = &ximage->data[ZINDEX(x, y, ximage)]; - dst = (char *) &px; - px = 0; - nbytes = (ibpp + 7) >> 3; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - ZNORMALIZE(&px, ximage); - _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); - ZNORMALIZE(&px, ximage); - src = (char *) &px; - dst = &ximage->data[ZINDEX(x, y, ximage)]; - for (i = nbytes; --i >= 0;) - *dst++ = *src++; - - return 1; -} - -#if !defined(WORD64) && !defined(LONG64) -static int -PutPixel32( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - unsigned char *addr; - - if(x < 0 || y < 0) - return 0; - - addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; - *((unsigned long *)addr) = pixel; - return 1; -} -#endif - -static int -PutPixel32MSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - unsigned char *addr; - - if(x < 0 || y < 0) - return 0; - - addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; - addr[0] = pixel >> 24; - addr[1] = pixel >> 16; - addr[2] = pixel >> 8; - addr[3] = pixel; - return 1; -} - -static int -PutPixel32LSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - unsigned char *addr; - - if(x < 0 || y < 0) - return 0; - - addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; - addr[3] = pixel >> 24; - addr[2] = pixel >> 16; - addr[1] = pixel >> 8; - addr[0] = pixel; - return 1; -} - -static int -PutPixel16MSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - unsigned char *addr; - - if(x < 0 || y < 0) - return 0; - - addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; - addr[0] = pixel >> 8; - addr[1] = pixel; - return 1; -} - -static int -PutPixel16LSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - unsigned char *addr; - - if(x < 0 || y < 0) - return 0; - - addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; - addr[1] = pixel >> 8; - addr[0] = pixel; - return 1; -} - -static int -PutPixel8( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - if(x < 0 || y < 0) - return 0; - - ximage->data[ZINDEX8(x, y, ximage)] = pixel; - return 1; -} - -static int -PutPixel1MSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - if(x < 0 || y < 0) - return 0; - - if (pixel & 1) - ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7); - else - ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7)); - return 1; -} - -static int -PutPixel1LSB( - register XImage *ximage, - int x, - int y, - unsigned long pixel) -{ - if(x < 0 || y < 0) - return 0; - - if (pixel & 1) - ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7); - else - ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7)); - return 1; -} - -#endif /* not FOR_MSW && not AMIGA */ - -/* - * This function parses an Xpm file or data and directly create an XImage - */ -int -xpmParseDataAndCreate( - Display *display, - xpmData *data, - XImage **image_return, - XImage **shapeimage_return, - XpmImage *image, - XpmInfo *info, - XpmAttributes *attributes) -{ - /* variables stored in the XpmAttributes structure */ - Visual *visual; - Colormap colormap; - unsigned int depth; - int bitmap_format; - XpmFreeColorsFunc freeColors; - - /* variables to return */ - XImage *ximage = NULL; - XImage *shapeimage = NULL; - unsigned int mask_pixel_index = XpmUndefPixel; - - /* calculation variables */ - Pixel *image_pixels = NULL; - Pixel *mask_pixels = NULL; - Pixel *alloc_pixels = NULL; - Pixel *used_pixels = NULL; - unsigned int nalloc_pixels = 0; - unsigned int nused_pixels = 0; - unsigned int width, height, ncolors, cpp; - unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; - XpmColor *colorTable = NULL; - char *hints_cmt = NULL; - char *colors_cmt = NULL; - char *pixels_cmt = NULL; - - unsigned int cmts; - int ErrorStatus; - xpmHashTable hashtable; - - - /* initialize return values */ - if (image_return) - *image_return = NULL; - if (shapeimage_return) - *shapeimage_return = NULL; - - - /* retrieve information from the XpmAttributes */ - if (attributes && (attributes->valuemask & XpmVisual)) - visual = attributes->visual; - else - visual = XDefaultVisual(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmColormap)) - colormap = attributes->colormap; - else - colormap = XDefaultColormap(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmDepth)) - depth = attributes->depth; - else - depth = XDefaultDepth(display, XDefaultScreen(display)); - - if (attributes && (attributes->valuemask & XpmBitmapFormat)) - bitmap_format = attributes->bitmap_format; - else - bitmap_format = ZPixmap; - - if (attributes && (attributes->valuemask & XpmFreeColors)) - freeColors = attributes->free_colors; - else - freeColors = FreeColors; - - cmts = info && (info->valuemask & XpmReturnComments); - - /* - * parse the header - */ - ErrorStatus = xpmParseHeader(data); - if (ErrorStatus != XpmSuccess) - return (ErrorStatus); - - /* - * read values - */ - ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, - &x_hotspot, &y_hotspot, &hotspot, - &extensions); - if (ErrorStatus != XpmSuccess) - return (ErrorStatus); - - /* - * store the hints comment line - */ - if (cmts) - xpmGetCmt(data, &hints_cmt); - - /* - * init the hashtable - */ - if (USE_HASHTABLE) { - ErrorStatus = xpmHashTableInit(&hashtable); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - } - - /* - * read colors - */ - ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - - /* - * store the colors comment line - */ - if (cmts) - xpmGetCmt(data, &colors_cmt); - - /* malloc pixels index tables */ - if (ncolors >= UINT_MAX / sizeof(Pixel)) - RETURN(XpmNoMemory); - - image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); - if (!image_pixels) - RETURN(XpmNoMemory); - - mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); - if (!mask_pixels) - RETURN(XpmNoMemory); - - /* maximum of allocated pixels will be the number of colors */ - alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); - if (!alloc_pixels) - RETURN(XpmNoMemory); - - /* maximum of allocated pixels will be the number of colors */ - used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); - if (!used_pixels) - RETURN(XpmNoMemory); - - /* get pixel colors, store them in index tables */ - ErrorStatus = CreateColors(display, attributes, colorTable, ncolors, - image_pixels, mask_pixels, &mask_pixel_index, - alloc_pixels, &nalloc_pixels, used_pixels, - &nused_pixels); - - if (ErrorStatus != XpmSuccess - && (ErrorStatus < 0 || (attributes - && (attributes->valuemask & XpmExactColors) - && attributes->exactColors))) - RETURN(ErrorStatus); - - /* now create the ximage */ - if (image_return) { - ErrorStatus = CreateXImage(display, visual, depth, - (depth == 1 ? bitmap_format : ZPixmap), - width, height, &ximage); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - -#if !defined(FOR_MSW) && !defined(AMIGA) - - /* - * set the XImage pointer function, to be used with XPutPixel, - * to an internal optimized function - */ - - if (ximage->bits_per_pixel == 8) - ximage->f.put_pixel = PutPixel8; - else if (((ximage->bits_per_pixel | ximage->depth) == 1) && - (ximage->byte_order == ximage->bitmap_bit_order)) - if (ximage->bitmap_bit_order == MSBFirst) - ximage->f.put_pixel = PutPixel1MSB; - else - ximage->f.put_pixel = PutPixel1LSB; - else if (ximage->bits_per_pixel == 16) - if (ximage->bitmap_bit_order == MSBFirst) - ximage->f.put_pixel = PutPixel16MSB; - else - ximage->f.put_pixel = PutPixel16LSB; - else if (ximage->bits_per_pixel == 32) -#if !defined(WORD64) && !defined(LONG64) - if (*((char *)&byteorderpixel) == ximage->byte_order) - ximage->f.put_pixel = PutPixel32; - else -#endif - if (ximage->bitmap_bit_order == MSBFirst) - ximage->f.put_pixel = PutPixel32MSB; - else - ximage->f.put_pixel = PutPixel32LSB; - else if ((ximage->bits_per_pixel | ximage->depth) == 1) - ximage->f.put_pixel = PutPixel1; - else - ximage->f.put_pixel = PutPixel; -#endif /* not FOR_MSW && not AMIGA */ - } - - /* create the shape mask image */ - if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { - ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, - width, height, &shapeimage); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - -#if !defined(FOR_MSW) && !defined(AMIGA) - if (shapeimage->bitmap_bit_order == MSBFirst) - shapeimage->f.put_pixel = PutPixel1MSB; - else - shapeimage->f.put_pixel = PutPixel1LSB; -#endif - } - - /* - * read pixels and put them in the XImage - */ - ErrorStatus = ParseAndPutPixels( -#ifdef FOR_MSW - display, -#endif - data, width, height, ncolors, cpp, - colorTable, &hashtable, - ximage, image_pixels, - shapeimage, mask_pixels); - XpmFree(image_pixels); - image_pixels = NULL; - XpmFree(mask_pixels); - mask_pixels = NULL; - - /* - * free the hastable - */ - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - else if (USE_HASHTABLE) - xpmHashTableFree(&hashtable); - - /* - * store the pixels comment line - */ - if (cmts) - xpmGetCmt(data, &pixels_cmt); - - /* - * parse extensions - */ - if (info && (info->valuemask & XpmReturnExtensions)) { - if (extensions) { - ErrorStatus = xpmParseExtensions(data, &info->extensions, - &info->nextensions); - if (ErrorStatus != XpmSuccess) - RETURN(ErrorStatus); - } else { - info->extensions = NULL; - info->nextensions = 0; - } - } - /* - * store found informations in the XpmImage structure - */ - image->width = width; - image->height = height; - image->cpp = cpp; - image->ncolors = ncolors; - image->colorTable = colorTable; - image->data = NULL; - - if (info) { - if (cmts) { - info->hints_cmt = hints_cmt; - info->colors_cmt = colors_cmt; - info->pixels_cmt = pixels_cmt; - } - if (hotspot) { - info->x_hotspot = x_hotspot; - info->y_hotspot = y_hotspot; - info->valuemask |= XpmHotspot; - } - } - /* if requested return used pixels in the XpmAttributes structure */ - if (attributes && (attributes->valuemask & XpmReturnPixels || -/* 3.2 backward compatibility code */ - attributes->valuemask & XpmReturnInfos)) { -/* end 3.2 bc */ - attributes->pixels = used_pixels; - attributes->npixels = nused_pixels; - attributes->mask_pixel = mask_pixel_index; - } else - XpmFree(used_pixels); - - /* if requested return alloc'ed pixels in the XpmAttributes structure */ - if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { - attributes->alloc_pixels = alloc_pixels; - attributes->nalloc_pixels = nalloc_pixels; - } else - XpmFree(alloc_pixels); - - /* return created images */ - if (image_return) - *image_return = ximage; - if (shapeimage_return) - *shapeimage_return = shapeimage; - - return (XpmSuccess); - -/* exit point in case of error, free only locally allocated variables */ -error: - if (USE_HASHTABLE) - xpmHashTableFree(&hashtable); - if (colorTable) - xpmFreeColorTable(colorTable, ncolors); - if (hints_cmt) - XpmFree(hints_cmt); - if (colors_cmt) - XpmFree(colors_cmt); - if (pixels_cmt) - XpmFree(pixels_cmt); - if (ximage) - XDestroyImage(ximage); - if (shapeimage) - XDestroyImage(shapeimage); - if (image_pixels) - XpmFree(image_pixels); - if (mask_pixels) - XpmFree(mask_pixels); - if (nalloc_pixels) - (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); - if (alloc_pixels) - XpmFree(alloc_pixels); - if (used_pixels) - XpmFree(used_pixels); - - return (ErrorStatus); -} - -static int -ParseAndPutPixels( -#ifdef FOR_MSW - Display *dc, -#endif - xpmData *data, - unsigned int width, - unsigned int height, - unsigned int ncolors, - unsigned int cpp, - XpmColor *colorTable, - xpmHashTable *hashtable, - XImage *image, - Pixel *image_pixels, - XImage *shapeimage, - Pixel *shape_pixels) -{ - unsigned int a, x, y; - - switch (cpp) { - - case (1): /* Optimize for single character - * colors */ - { - unsigned short colidx[256]; -#ifdef FOR_MSW - HDC shapedc; - HBITMAP obm, sobm; - - if ( shapeimage ) { - shapedc = CreateCompatibleDC(*dc); - sobm = SelectObject(shapedc, shapeimage->bitmap); - } else { - shapedc = NULL; - } - obm = SelectObject(*dc, image->bitmap); -#endif - if (ncolors > 256) - return (XpmFileInvalid); - - bzero((char *)colidx, 256 * sizeof(short)); - for (a = 0; a < ncolors; a++) - colidx[(unsigned char)colorTable[a].string[0]] = a + 1; - - for (y = 0; y < height; y++) { - xpmNextString(data); - for (x = 0; x < width; x++) { - int c = xpmGetC(data); - - if (c > 0 && c < 256 && colidx[c] != 0) { -#ifndef FOR_MSW - XPutPixel(image, x, y, image_pixels[colidx[c] - 1]); - if (shapeimage) - XPutPixel(shapeimage, x, y, - shape_pixels[colidx[c] - 1]); -#else - SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]); - if (shapedc) { - SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]); - } -#endif - } else - return (XpmFileInvalid); - } - } -#ifdef FOR_MSW - if ( shapedc ) { - SelectObject(shapedc, sobm); - DeleteDC(shapedc); - } - SelectObject(*dc, obm); -#endif - } - break; - - case (2): /* Optimize for double character - * colors */ - { - -/* free all allocated pointers at all exits */ -#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \ -if (cidx[f]) XpmFree(cidx[f]);} - - /* array of pointers malloced by need */ - unsigned short *cidx[256]; - unsigned int char1; - - bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ - for (a = 0; a < ncolors; a++) { - char1 = (unsigned char) colorTable[a].string[0]; - if (cidx[char1] == NULL) { /* get new memory */ - cidx[char1] = (unsigned short *) - XpmCalloc(256, sizeof(unsigned short)); - if (cidx[char1] == NULL) { /* new block failed */ - FREE_CIDX; - return (XpmNoMemory); - } - } - cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; - } - - for (y = 0; y < height; y++) { - xpmNextString(data); - for (x = 0; x < width; x++) { - int cc1 = xpmGetC(data); - if (cc1 > 0 && cc1 < 256) { - int cc2 = xpmGetC(data); - if (cc2 > 0 && cc2 < 256 && - cidx[cc1] && cidx[cc1][cc2] != 0) { -#ifndef FOR_MSW - XPutPixel(image, x, y, - image_pixels[cidx[cc1][cc2] - 1]); - if (shapeimage) - XPutPixel(shapeimage, x, y, - shape_pixels[cidx[cc1][cc2] - 1]); -#else - SelectObject(*dc, image->bitmap); - SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]); - if (shapeimage) { - SelectObject(*dc, shapeimage->bitmap); - SetPixel(*dc, x, y, - shape_pixels[cidx[cc1][cc2] - 1]); - } -#endif - } else { - FREE_CIDX; - return (XpmFileInvalid); - } - } else { - FREE_CIDX; - return (XpmFileInvalid); - } - } - } - FREE_CIDX; - } - break; - - default: /* Non-optimized case of long color - * names */ - { - char *s; - char buf[BUFSIZ]; - - if (cpp >= sizeof(buf)) - return (XpmFileInvalid); - - buf[cpp] = '\0'; - if (USE_HASHTABLE) { - xpmHashAtom *slot; - - for (y = 0; y < height; y++) { - xpmNextString(data); - for (x = 0; x < width; x++) { - for (a = 0, s = buf; a < cpp; a++, s++) - *s = xpmGetC(data); - slot = xpmHashSlot(hashtable, buf); - if (!*slot) /* no color matches */ - return (XpmFileInvalid); -#ifndef FOR_MSW - XPutPixel(image, x, y, - image_pixels[HashColorIndex(slot)]); - if (shapeimage) - XPutPixel(shapeimage, x, y, - shape_pixels[HashColorIndex(slot)]); -#else - SelectObject(*dc, image->bitmap); - SetPixel(*dc, x, y, - image_pixels[HashColorIndex(slot)]); - if (shapeimage) { - SelectObject(*dc, shapeimage->bitmap); - SetPixel(*dc, x, y, - shape_pixels[HashColorIndex(slot)]); - } -#endif - } - } - } else { - for (y = 0; y < height; y++) { - xpmNextString(data); - for (x = 0; x < width; x++) { - for (a = 0, s = buf; a < cpp; a++, s++) - *s = xpmGetC(data); - for (a = 0; a < ncolors; a++) - if (!strcmp(colorTable[a].string, buf)) - break; - if (a == ncolors) /* no color matches */ - return (XpmFileInvalid); -#ifndef FOR_MSW - XPutPixel(image, x, y, image_pixels[a]); - if (shapeimage) - XPutPixel(shapeimage, x, y, shape_pixels[a]); -#else - SelectObject(*dc, image->bitmap); - SetPixel(*dc, x, y, image_pixels[a]); - if (shapeimage) { - SelectObject(*dc, shapeimage->bitmap); - SetPixel(*dc, x, y, shape_pixels[a]); - } -#endif - } - } - } - } - break; - } - return (XpmSuccess); -} +/*
+ * Copyright (C) 1989-95 GROUPE BULL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of GROUPE BULL shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from GROUPE BULL.
+ */
+
+/*****************************************************************************\
+* create.c: *
+* *
+* XPM library *
+* Create an X image and possibly its related shape mask *
+* from the given XpmImage. *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+/*
+ * The code related to FOR_MSW has been added by
+ * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
+ */
+
+/*
+ * The code related to AMIGA has been added by
+ * Lorens Younes (d93-hyo@nada.kth.se) 4/96
+ */
+
+/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "XpmI.h"
+#include <ctype.h>
+
+LFUNC(xpmVisualType, int, (Visual *visual));
+
+LFUNC(AllocColor, int, (Display *display, Colormap colormap,
+ char *colorname, XColor *xcolor, void *closure));
+LFUNC(FreeColors, int, (Display *display, Colormap colormap,
+ Pixel *pixels, int n, void *closure));
+
+#ifndef FOR_MSW
+LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
+ Visual *visual, XColor *col,
+ Pixel *image_pixel, Pixel *mask_pixel,
+ Pixel *alloc_pixels, unsigned int *nalloc_pixels,
+ XpmAttributes *attributes, XColor *cols, int ncols,
+ XpmAllocColorFunc allocColor, void *closure));
+#else
+/* let the window system take care of close colors */
+#endif
+
+LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
+ char *colorname, unsigned int color_index,
+ Pixel *image_pixel, Pixel *mask_pixel,
+ unsigned int *mask_pixel_index,
+ Pixel *alloc_pixels, unsigned int *nalloc_pixels,
+ Pixel *used_pixels, unsigned int *nused_pixels,
+ XpmAttributes *attributes, XColor *cols, int ncols,
+ XpmAllocColorFunc allocColor, void *closure));
+
+LFUNC(CreateXImage, int, (Display *display, Visual *visual,
+ unsigned int depth, int format, unsigned int width,
+ unsigned int height, XImage **image_return));
+
+LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
+ XpmColor *colors, unsigned int ncolors,
+ Pixel *image_pixels, Pixel *mask_pixels,
+ unsigned int *mask_pixel_index,
+ Pixel *alloc_pixels, unsigned int *nalloc_pixels,
+ Pixel *used_pixels, unsigned int *nused_pixels));
+
+#ifndef FOR_MSW
+LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
+ unsigned int height, unsigned int ncolors,
+ unsigned int cpp, XpmColor *colorTable,
+ xpmHashTable *hashtable,
+ XImage *image, Pixel *image_pixels,
+ XImage *mask, Pixel *mask_pixels));
+#else /* FOR_MSW */
+LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
+ unsigned int height, unsigned int ncolors,
+ unsigned int cpp, XpmColor *colorTable,
+ xpmHashTable *hashtable,
+ XImage *image, Pixel *image_pixels,
+ XImage *mask, Pixel *mask_pixels));
+#endif
+
+#ifndef FOR_MSW
+# ifndef AMIGA
+/* XImage pixel routines */
+LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+
+LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+
+LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+
+LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+
+LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+
+LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
+#if !defined(WORD64) && !defined(LONG64)
+LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
+#endif
+LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
+
+# else /* AMIGA */
+LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel *pixels));
+# endif/* AMIGA */
+#else /* FOR_MSW */
+/* FOR_MSW pixel routine */
+LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
+ unsigned int width, unsigned int height,
+ unsigned int *pixelindex, Pixel *pixels));
+#endif /* FOR_MSW */
+
+#ifdef NEED_STRCASECMP
+FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
+
+/*
+ * in case strcasecmp is not provided by the system here is one
+ * which does the trick
+ */
+int
+xpmstrcasecmp(
+ register char *s1,
+ register char *s2)
+{
+ register int c1, c2;
+
+ while (*s1 && *s2) {
+ c1 = tolower(*s1);
+ c2 = tolower(*s2);
+ if (c1 != c2)
+ return (c1 - c2);
+ s1++;
+ s2++;
+ }
+ return (int) (*s1 - *s2);
+}
+
+#endif
+
+/*
+ * return the default color key related to the given visual
+ */
+static int
+xpmVisualType(Visual *visual)
+{
+#ifndef FOR_MSW
+# ifndef AMIGA
+ switch (visual->class) {
+ case StaticGray:
+ case GrayScale:
+ switch (visual->map_entries) {
+ case 2:
+ return (XPM_MONO);
+ case 4:
+ return (XPM_GRAY4);
+ default:
+ return (XPM_GRAY);
+ }
+ default:
+ return (XPM_COLOR);
+ }
+# else
+ /* set the key explicitly in the XpmAttributes to override this */
+ return (XPM_COLOR);
+# endif
+#else
+ /* there should be a similar switch for MSW */
+ return (XPM_COLOR);
+#endif
+}
+
+
+typedef struct {
+ int cols_index;
+ long closeness;
+} CloseColor;
+
+static int
+closeness_cmp(Const void *a, Const void *b)
+{
+ CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
+
+ /* cast to int as qsort requires */
+ return (int) (x->closeness - y->closeness);
+}
+
+
+/* default AllocColor function:
+ * call XParseColor if colorname is given, return negative value if failure
+ * call XAllocColor and return 0 if failure, positive otherwise
+ */
+static int
+AllocColor(
+ Display *display,
+ Colormap colormap,
+ char *colorname,
+ XColor *xcolor,
+ void *closure) /* not used */
+{
+ int status;
+ if (colorname)
+ if (!XParseColor(display, colormap, colorname, xcolor))
+ return -1;
+ status = XAllocColor(display, colormap, xcolor);
+ return status != 0 ? 1 : 0;
+}
+
+
+#ifndef FOR_MSW
+/*
+ * set a close color in case the exact one can't be set
+ * return 0 if success, 1 otherwise.
+ */
+
+static int
+SetCloseColor(
+ Display *display,
+ Colormap colormap,
+ Visual *visual,
+ XColor *col,
+ Pixel *image_pixel,
+ Pixel *mask_pixel,
+ Pixel *alloc_pixels,
+ unsigned int *nalloc_pixels,
+ XpmAttributes *attributes,
+ XColor *cols,
+ int ncols,
+ XpmAllocColorFunc allocColor,
+ void *closure)
+{
+
+ /*
+ * Allocation failed, so try close colors. To get here the visual must
+ * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
+ * What about sharing systems like QDSS?). Beware: we have to treat
+ * DirectColor differently.
+ */
+
+
+ long int red_closeness, green_closeness, blue_closeness;
+ int n;
+ Bool alloc_color;
+
+ if (attributes && (attributes->valuemask & XpmCloseness))
+ red_closeness = green_closeness = blue_closeness =
+ attributes->closeness;
+ else {
+ red_closeness = attributes->red_closeness;
+ green_closeness = attributes->green_closeness;
+ blue_closeness = attributes->blue_closeness;
+ }
+ if (attributes && (attributes->valuemask & XpmAllocCloseColors))
+ alloc_color = attributes->alloc_close_colors;
+ else
+ alloc_color = True;
+
+ /*
+ * We sort the colormap by closeness and try to allocate the color
+ * closest to the target. If the allocation of this close color fails,
+ * which almost never happens, then one of two scenarios is possible.
+ * Either the colormap must have changed (since the last close color
+ * allocation or possibly while we were sorting the colormap), or the
+ * color is allocated as Read/Write by some other client. (Note: X
+ * _should_ allow clients to check if a particular color is Read/Write,
+ * but it doesn't! :-( ). We cannot determine which of these scenarios
+ * occurred, so we try the next closest color, and so on, until no more
+ * colors are within closeness of the target. If we knew that the
+ * colormap had changed, we could skip this sequence.
+ *
+ * If _none_ of the colors within closeness of the target can be allocated,
+ * then we can finally be pretty sure that the colormap has actually
+ * changed. In this case we try to allocate the original color (again),
+ * then try the closecolor stuff (again)...
+ *
+ * In theory it would be possible for an infinite loop to occur if another
+ * process kept changing the colormap every time we sorted it, so we set
+ * a maximum on the number of iterations. After this many tries, we use
+ * XGrabServer() to ensure that the colormap remains unchanged.
+ *
+ * This approach gives particularly bad worst case performance - as many as
+ * <MaximumIterations> colormap reads and sorts may be needed, and as
+ * many as <MaximumIterations> * <ColormapSize> attempted allocations
+ * may fail. On an 8-bit system, this means as many as 3 colormap reads,
+ * 3 sorts and 768 failed allocations per execution of this code!
+ * Luckily, my experiments show that in general use in a typical 8-bit
+ * color environment only about 1 in every 10000 allocations fails to
+ * succeed in the fastest possible time. So virtually every time what
+ * actually happens is a single sort followed by a successful allocate.
+ * The very first allocation also costs a colormap read, but no further
+ * reads are usually necessary.
+ */
+
+#define ITERATIONS 2 /* more than one is almost never
+ * necessary */
+
+ for (n = 0; n <= ITERATIONS; ++n) {
+ CloseColor *closenesses =
+ (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
+ int i, c;
+
+ for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */
+#define COLOR_FACTOR 3
+#define BRIGHTNESS_FACTOR 1
+
+ closenesses[i].cols_index = i;
+ closenesses[i].closeness =
+ COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
+ + abs((long) col->green - (long) cols[i].green)
+ + abs((long) col->blue - (long) cols[i].blue))
+ + BRIGHTNESS_FACTOR * abs(((long) col->red +
+ (long) col->green +
+ (long) col->blue)
+ - ((long) cols[i].red +
+ (long) cols[i].green +
+ (long) cols[i].blue));
+ }
+ qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
+
+ i = 0;
+ c = closenesses[i].cols_index;
+ while ((long) cols[c].red >= (long) col->red - red_closeness &&
+ (long) cols[c].red <= (long) col->red + red_closeness &&
+ (long) cols[c].green >= (long) col->green - green_closeness &&
+ (long) cols[c].green <= (long) col->green + green_closeness &&
+ (long) cols[c].blue >= (long) col->blue - blue_closeness &&
+ (long) cols[c].blue <= (long) col->blue + blue_closeness) {
+ if (alloc_color) {
+ if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
+ if (n == ITERATIONS)
+ XUngrabServer(display);
+ XpmFree(closenesses);
+ *image_pixel = cols[c].pixel;
+ *mask_pixel = 1;
+ alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
+ return (0);
+ } else {
+ ++i;
+ if (i == ncols)
+ break;
+ c = closenesses[i].cols_index;
+ }
+ } else {
+ if (n == ITERATIONS)
+ XUngrabServer(display);
+ XpmFree(closenesses);
+ *image_pixel = cols[c].pixel;
+ *mask_pixel = 1;
+ return (0);
+ }
+ }
+
+ /* Couldn't allocate _any_ of the close colors! */
+
+ if (n == ITERATIONS)
+ XUngrabServer(display);
+ XpmFree(closenesses);
+
+ if (i == 0 || i == ncols) /* no color close enough or cannot */
+ return (1); /* alloc any color (full of r/w's) */
+
+ if ((*allocColor)(display, colormap, NULL, col, closure)) {
+ *image_pixel = col->pixel;
+ *mask_pixel = 1;
+ alloc_pixels[(*nalloc_pixels)++] = col->pixel;
+ return (0);
+ } else { /* colormap has probably changed, so
+ * re-read... */
+ if (n == ITERATIONS - 1)
+ XGrabServer(display);
+
+#if 0
+ if (visual->class == DirectColor) {
+ /* TODO */
+ } else
+#endif
+ XQueryColors(display, colormap, cols, ncols);
+ }
+ }
+ return (1);
+}
+
+#define USE_CLOSECOLOR attributes && \
+(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
+ || ((attributes->valuemask & XpmRGBCloseness) && \
+ (attributes->red_closeness != 0 \
+ || attributes->green_closeness != 0 \
+ || attributes->blue_closeness != 0)))
+
+#else
+ /* FOR_MSW part */
+ /* nothing to do here, the window system does it */
+#endif
+
+/*
+ * set the color pixel related to the given colorname,
+ * return 0 if success, 1 otherwise.
+ */
+
+static int
+SetColor(
+ Display *display,
+ Colormap colormap,
+ Visual *visual,
+ char *colorname,
+ unsigned int color_index,
+ Pixel *image_pixel,
+ Pixel *mask_pixel,
+ unsigned int *mask_pixel_index,
+ Pixel *alloc_pixels,
+ unsigned int *nalloc_pixels,
+ Pixel *used_pixels,
+ unsigned int *nused_pixels,
+ XpmAttributes *attributes,
+ XColor *cols,
+ int ncols,
+ XpmAllocColorFunc allocColor,
+ void *closure)
+{
+ XColor xcolor;
+ int status;
+
+ if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
+ status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
+ if (status < 0) /* parse color failed */
+ return (1);
+
+ if (status == 0) {
+#ifndef FOR_MSW
+ if (USE_CLOSECOLOR)
+ return (SetCloseColor(display, colormap, visual, &xcolor,
+ image_pixel, mask_pixel,
+ alloc_pixels, nalloc_pixels,
+ attributes, cols, ncols,
+ allocColor, closure));
+ else
+#endif /* ndef FOR_MSW */
+ return (1);
+ } else
+ alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
+ *image_pixel = xcolor.pixel;
+#ifndef FOR_MSW
+ *mask_pixel = 1;
+#else
+ *mask_pixel = RGB(0,0,0);
+#endif
+ used_pixels[(*nused_pixels)++] = xcolor.pixel;
+ } else {
+ *image_pixel = 0;
+#ifndef FOR_MSW
+ *mask_pixel = 0;
+#else
+ *mask_pixel = RGB(255,255,255);
+#endif
+ /* store the color table index */
+ *mask_pixel_index = color_index;
+ }
+ return (0);
+}
+
+
+static int
+CreateColors(
+ Display *display,
+ XpmAttributes *attributes,
+ XpmColor *colors,
+ unsigned int ncolors,
+ Pixel *image_pixels,
+ Pixel *mask_pixels,
+ unsigned int *mask_pixel_index,
+ Pixel *alloc_pixels,
+ unsigned int *nalloc_pixels,
+ Pixel *used_pixels,
+ unsigned int *nused_pixels)
+{
+ /* variables stored in the XpmAttributes structure */
+ Visual *visual;
+ Colormap colormap;
+ XpmColorSymbol *colorsymbols = NULL;
+ unsigned int numsymbols;
+ XpmAllocColorFunc allocColor;
+ void *closure;
+
+ char *colorname;
+ unsigned int color, key;
+ Bool pixel_defined;
+ XpmColorSymbol *symbol = NULL;
+ char **defaults;
+ int ErrorStatus = XpmSuccess;
+ char *s;
+ int default_index;
+
+ XColor *cols = NULL;
+ unsigned int ncols = 0;
+
+ /*
+ * retrieve information from the XpmAttributes
+ */
+ if (attributes && attributes->valuemask & XpmColorSymbols) {
+ colorsymbols = attributes->colorsymbols;
+ numsymbols = attributes->numsymbols;
+ } else
+ numsymbols = 0;
+
+ if (attributes && attributes->valuemask & XpmVisual)
+ visual = attributes->visual;
+ else
+ visual = XDefaultVisual(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmColormap))
+ colormap = attributes->colormap;
+ else
+ colormap = XDefaultColormap(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmColorKey))
+ key = attributes->color_key;
+ else
+ key = xpmVisualType(visual);
+
+ if (attributes && (attributes->valuemask & XpmAllocColor))
+ allocColor = attributes->alloc_color;
+ else
+ allocColor = AllocColor;
+ if (attributes && (attributes->valuemask & XpmColorClosure))
+ closure = attributes->color_closure;
+ else
+ closure = NULL;
+
+#ifndef FOR_MSW
+ if (USE_CLOSECOLOR) {
+ /* originally from SetCloseColor */
+#if 0
+ if (visual->class == DirectColor) {
+
+ /*
+ * TODO: Implement close colors for DirectColor visuals. This is
+ * difficult situation. Chances are that we will never get here,
+ * because any machine that supports DirectColor will probably
+ * also support TrueColor (and probably PseudoColor). Also,
+ * DirectColor colormaps can be very large, so looking for close
+ * colors may be too slow.
+ */
+ } else {
+#endif
+ unsigned int i;
+
+#ifndef AMIGA
+ ncols = visual->map_entries;
+#else
+ ncols = colormap->Count;
+#endif
+ cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
+ for (i = 0; i < ncols; ++i)
+ cols[i].pixel = i;
+ XQueryColors(display, colormap, cols, ncols);
+#if 0
+ }
+#endif
+ }
+#endif /* ndef FOR_MSW */
+
+ switch (key) {
+ case XPM_MONO:
+ default_index = 2;
+ break;
+ case XPM_GRAY4:
+ default_index = 3;
+ break;
+ case XPM_GRAY:
+ default_index = 4;
+ break;
+ case XPM_COLOR:
+ default:
+ default_index = 5;
+ break;
+ }
+
+ for (color = 0; color < ncolors; color++, colors++,
+ image_pixels++, mask_pixels++) {
+ colorname = NULL;
+ pixel_defined = False;
+ defaults = (char **) colors;
+
+ /*
+ * look for a defined symbol
+ */
+ if (numsymbols) {
+
+ unsigned int n;
+
+ s = defaults[1];
+ for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
+ if (symbol->name && s && !strcmp(symbol->name, s))
+ /* override name */
+ break;
+ if (!symbol->name && symbol->value) { /* override value */
+ int def_index = default_index;
+
+ while (defaults[def_index] == NULL) /* find defined
+ * colorname */
+ --def_index;
+ if (def_index < 2) {/* nothing towards mono, so try
+ * towards color */
+ def_index = default_index + 1;
+ while (def_index <= 5 && defaults[def_index] == NULL)
+ ++def_index;
+ }
+ if (def_index >= 2 && defaults[def_index] != NULL &&
+ !xpmstrcasecmp(symbol->value, defaults[def_index]))
+ break;
+ }
+ }
+ if (n != numsymbols) {
+ if (symbol->name && symbol->value)
+ colorname = symbol->value;
+ else
+ pixel_defined = True;
+ }
+ }
+ if (!pixel_defined) { /* pixel not given as symbol value */
+
+ unsigned int k;
+
+ if (colorname) { /* colorname given as symbol value */
+ if (!SetColor(display, colormap, visual, colorname, color,
+ image_pixels, mask_pixels, mask_pixel_index,
+ alloc_pixels, nalloc_pixels, used_pixels,
+ nused_pixels, attributes, cols, ncols,
+ allocColor, closure))
+ pixel_defined = True;
+ else
+ ErrorStatus = XpmColorError;
+ }
+ k = key;
+ while (!pixel_defined && k > 1) {
+ if (defaults[k]) {
+ if (!SetColor(display, colormap, visual, defaults[k],
+ color, image_pixels, mask_pixels,
+ mask_pixel_index, alloc_pixels,
+ nalloc_pixels, used_pixels, nused_pixels,
+ attributes, cols, ncols,
+ allocColor, closure)) {
+ pixel_defined = True;
+ break;
+ } else
+ ErrorStatus = XpmColorError;
+ }
+ k--;
+ }
+ k = key + 1;
+ while (!pixel_defined && k < NKEYS + 1) {
+ if (defaults[k]) {
+ if (!SetColor(display, colormap, visual, defaults[k],
+ color, image_pixels, mask_pixels,
+ mask_pixel_index, alloc_pixels,
+ nalloc_pixels, used_pixels, nused_pixels,
+ attributes, cols, ncols,
+ allocColor, closure)) {
+ pixel_defined = True;
+ break;
+ } else
+ ErrorStatus = XpmColorError;
+ }
+ k++;
+ }
+ if (!pixel_defined) {
+ if (cols)
+ XpmFree(cols);
+ return (XpmColorFailed);
+ }
+ } else {
+ /* simply use the given pixel */
+ *image_pixels = symbol->pixel;
+ /* the following makes the mask to be built even if none
+ is given a particular pixel */
+ if (symbol->value
+ && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
+ *mask_pixels = 0;
+ *mask_pixel_index = color;
+ } else
+ *mask_pixels = 1;
+ used_pixels[(*nused_pixels)++] = *image_pixels;
+ }
+ }
+ if (cols)
+ XpmFree(cols);
+ return (ErrorStatus);
+}
+
+
+/* default FreeColors function, simply call XFreeColors */
+static int
+FreeColors(
+ Display *display,
+ Colormap colormap,
+ Pixel *pixels,
+ int n,
+ void *closure) /* not used */
+{
+ return XFreeColors(display, colormap, pixels, n, 0);
+}
+
+
+/* function call in case of error */
+
+#undef RETURN
+#define RETURN(status) \
+do \
+{ \
+ ErrorStatus = status; \
+ goto error; \
+} while(0)
+
+int
+XpmCreateImageFromXpmImage(
+ Display *display,
+ XpmImage *image,
+ XImage **image_return,
+ XImage **shapeimage_return,
+ XpmAttributes *attributes)
+{
+ /* variables stored in the XpmAttributes structure */
+ Visual *visual;
+ Colormap colormap;
+ unsigned int depth;
+ int bitmap_format;
+ XpmFreeColorsFunc freeColors;
+
+ /* variables to return */
+ XImage *ximage = NULL;
+ XImage *shapeimage = NULL;
+ unsigned int mask_pixel_index = XpmUndefPixel;
+ int ErrorStatus;
+
+ /* calculation variables */
+ Pixel *image_pixels = NULL;
+ Pixel *mask_pixels = NULL;
+ Pixel *alloc_pixels = NULL;
+ Pixel *used_pixels = NULL;
+ unsigned int nalloc_pixels = 0;
+ unsigned int nused_pixels = 0;
+
+ /* initialize return values */
+ if (image_return)
+ *image_return = NULL;
+ if (shapeimage_return)
+ *shapeimage_return = NULL;
+
+ /* retrieve information from the XpmAttributes */
+ if (attributes && (attributes->valuemask & XpmVisual))
+ visual = attributes->visual;
+ else
+ visual = XDefaultVisual(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmColormap))
+ colormap = attributes->colormap;
+ else
+ colormap = XDefaultColormap(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmDepth))
+ depth = attributes->depth;
+ else
+ depth = XDefaultDepth(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmBitmapFormat))
+ bitmap_format = attributes->bitmap_format;
+ else
+ bitmap_format = ZPixmap;
+
+ if (attributes && (attributes->valuemask & XpmFreeColors))
+ freeColors = attributes->free_colors;
+ else
+ freeColors = FreeColors;
+
+ ErrorStatus = XpmSuccess;
+
+ if (image->ncolors >= UINT_MAX / sizeof(Pixel))
+ return (XpmNoMemory);
+
+ /* malloc pixels index tables */
+ image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
+ if (!image_pixels)
+ return (XpmNoMemory);
+
+ mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
+ if (!mask_pixels)
+ RETURN(XpmNoMemory);
+
+ /* maximum of allocated pixels will be the number of colors */
+ alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
+ if (!alloc_pixels)
+ RETURN(XpmNoMemory);
+
+ /* maximum of allocated pixels will be the number of colors */
+ used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
+ if (!used_pixels)
+ RETURN(XpmNoMemory);
+
+ /* get pixel colors, store them in index tables */
+ ErrorStatus = CreateColors(display, attributes, image->colorTable,
+ image->ncolors, image_pixels, mask_pixels,
+ &mask_pixel_index, alloc_pixels, &nalloc_pixels,
+ used_pixels, &nused_pixels);
+
+ if (ErrorStatus != XpmSuccess
+ && (ErrorStatus < 0 || (attributes
+ && (attributes->valuemask & XpmExactColors)
+ && attributes->exactColors)))
+ RETURN(ErrorStatus);
+
+ /* create the ximage */
+ if (image_return) {
+ ErrorStatus = CreateXImage(display, visual, depth,
+ (depth == 1 ? bitmap_format : ZPixmap),
+ image->width, image->height, &ximage);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+#ifndef FOR_MSW
+# ifndef AMIGA
+
+ /*
+ * set the ximage data using optimized functions for ZPixmap
+ */
+
+ if (ximage->bits_per_pixel == 8)
+ PutImagePixels8(ximage, image->width, image->height,
+ image->data, image_pixels);
+ else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
+ (ximage->byte_order == ximage->bitmap_bit_order))
+ PutImagePixels1(ximage, image->width, image->height,
+ image->data, image_pixels);
+ else if (ximage->bits_per_pixel == 16)
+ PutImagePixels16(ximage, image->width, image->height,
+ image->data, image_pixels);
+ else if (ximage->bits_per_pixel == 32)
+ PutImagePixels32(ximage, image->width, image->height,
+ image->data, image_pixels);
+ else
+ PutImagePixels(ximage, image->width, image->height,
+ image->data, image_pixels);
+# else /* AMIGA */
+ APutImagePixels(ximage, image->width, image->height,
+ image->data, image_pixels);
+# endif
+#else /* FOR_MSW */
+ MSWPutImagePixels(display, ximage, image->width, image->height,
+ image->data, image_pixels);
+#endif
+ }
+ /* create the shape mask image */
+ if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
+ ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
+ image->width, image->height, &shapeimage);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+#ifndef FOR_MSW
+# ifndef AMIGA
+ PutImagePixels1(shapeimage, image->width, image->height,
+ image->data, mask_pixels);
+# else /* AMIGA */
+ APutImagePixels(shapeimage, image->width, image->height,
+ image->data, mask_pixels);
+# endif
+#else /* FOR_MSW */
+ MSWPutImagePixels(display, shapeimage, image->width, image->height,
+ image->data, mask_pixels);
+#endif
+
+ }
+ XpmFree(image_pixels);
+ XpmFree(mask_pixels);
+
+ /* if requested return used pixels in the XpmAttributes structure */
+ if (attributes && (attributes->valuemask & XpmReturnPixels ||
+/* 3.2 backward compatibility code */
+ attributes->valuemask & XpmReturnInfos)) {
+/* end 3.2 bc */
+ attributes->pixels = used_pixels;
+ attributes->npixels = nused_pixels;
+ attributes->mask_pixel = mask_pixel_index;
+ } else
+ XpmFree(used_pixels);
+
+ /* if requested return alloc'ed pixels in the XpmAttributes structure */
+ if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
+ attributes->alloc_pixels = alloc_pixels;
+ attributes->nalloc_pixels = nalloc_pixels;
+ } else
+ XpmFree(alloc_pixels);
+
+ /* return created images */
+ if (image_return)
+ *image_return = ximage;
+ if (shapeimage_return)
+ *shapeimage_return = shapeimage;
+
+ return (ErrorStatus);
+
+/* exit point in case of error, free only locally allocated variables */
+error:
+ if (ximage)
+ XDestroyImage(ximage);
+ if (shapeimage)
+ XDestroyImage(shapeimage);
+ if (image_pixels)
+ XpmFree(image_pixels);
+ if (mask_pixels)
+ XpmFree(mask_pixels);
+ if (nalloc_pixels)
+ (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
+ if (alloc_pixels)
+ XpmFree(alloc_pixels);
+ if (used_pixels)
+ XpmFree(used_pixels);
+
+ return (ErrorStatus);
+}
+
+
+/*
+ * Create an XImage with its data
+ */
+static int
+CreateXImage(
+ Display *display,
+ Visual *visual,
+ unsigned int depth,
+ int format,
+ unsigned int width,
+ unsigned int height,
+ XImage **image_return)
+{
+ int bitmap_pad;
+
+ /* first get bitmap_pad */
+ if (depth > 16)
+ bitmap_pad = 32;
+ else if (depth > 8)
+ bitmap_pad = 16;
+ else
+ bitmap_pad = 8;
+
+ /* then create the XImage with data = NULL and bytes_per_line = 0 */
+ *image_return = XCreateImage(display, visual, depth, format, 0, 0,
+ width, height, bitmap_pad, 0);
+ if (!*image_return)
+ return (XpmNoMemory);
+
+#if !defined(FOR_MSW) && !defined(AMIGA)
+ if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
+ XDestroyImage(*image_return);
+ return XpmNoMemory;
+ }
+ /* now that bytes_per_line must have been set properly alloc data */
+ if((*image_return)->bytes_per_line == 0 || height == 0)
+ return XpmNoMemory;
+ (*image_return)->data =
+ (char *) XpmMalloc((*image_return)->bytes_per_line * height);
+
+ if (!(*image_return)->data) {
+ XDestroyImage(*image_return);
+ *image_return = NULL;
+ return (XpmNoMemory);
+ }
+#else
+ /* under FOR_MSW and AMIGA XCreateImage has done it all */
+#endif
+ return (XpmSuccess);
+}
+
+#ifndef FOR_MSW
+# ifndef AMIGA
+/*
+ * The functions below are written from X11R5 MIT's code (XImUtil.c)
+ *
+ * The idea is to have faster functions than the standard XPutPixel function
+ * to build the image data. Indeed we can speed up things by suppressing tests
+ * performed for each pixel. We do the same tests but at the image level.
+ * We also assume that we use only ZPixmap images with null offsets.
+ */
+
+LFUNC(_putbits, void, (register char *src, int dstoffset,
+ register int numbits, register char *dst));
+
+LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
+
+static unsigned char Const _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+static int
+_XReverse_Bytes(
+ register unsigned char *bpt,
+ register unsigned int nb)
+{
+ do {
+ *bpt = _reverse_byte[*bpt];
+ bpt++;
+ } while (--nb > 0); /* is nb user-controled? */
+ return 0;
+}
+
+
+void
+xpm_xynormalizeimagebits(
+ register unsigned char *bp,
+ register XImage *img)
+{
+ register unsigned char c;
+
+ if (img->byte_order != img->bitmap_bit_order) {
+ switch (img->bitmap_unit) {
+
+ case 16:
+ c = *bp;
+ *bp = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+
+ case 32:
+ c = *(bp + 3);
+ *(bp + 3) = *bp;
+ *bp = c;
+ c = *(bp + 2);
+ *(bp + 2) = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+ }
+ }
+ if (img->bitmap_bit_order == MSBFirst)
+ _XReverse_Bytes(bp, img->bitmap_unit >> 3);
+}
+
+void
+xpm_znormalizeimagebits(
+ register unsigned char *bp,
+ register XImage *img)
+{
+ register unsigned char c;
+
+ switch (img->bits_per_pixel) {
+
+ case 2:
+ _XReverse_Bytes(bp, 1);
+ break;
+
+ case 4:
+ *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
+ break;
+
+ case 16:
+ c = *bp;
+ *bp = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+
+ case 24:
+ c = *(bp + 2);
+ *(bp + 2) = *bp;
+ *bp = c;
+ break;
+
+ case 32:
+ c = *(bp + 3);
+ *(bp + 3) = *bp;
+ *bp = c;
+ c = *(bp + 2);
+ *(bp + 2) = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+ }
+}
+
+static unsigned char Const _lomask[0x09] = {
+0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+static unsigned char Const _himask[0x09] = {
+0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+
+static void
+_putbits(
+ register char *src, /* address of source bit string */
+ int dstoffset, /* bit offset into destination;
+ * range is 0-31 */
+ register int numbits, /* number of bits to copy to
+ * destination */
+ register char *dst) /* address of destination bit string */
+{
+ register unsigned char chlo, chhi;
+ int hibits;
+
+ dst = dst + (dstoffset >> 3);
+ dstoffset = dstoffset & 7;
+ hibits = 8 - dstoffset;
+ chlo = *dst & _lomask[dstoffset];
+ for (;;) {
+ chhi = (*src << dstoffset) & _himask[dstoffset];
+ if (numbits <= hibits) {
+ chhi = chhi & _lomask[dstoffset + numbits];
+ *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
+ break;
+ }
+ *dst = chhi | chlo;
+ dst++;
+ numbits = numbits - hibits;
+ chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
+ src++;
+ if (numbits <= dstoffset) {
+ chlo = chlo & _lomask[numbits];
+ *dst = (*dst & _himask[numbits]) | chlo;
+ break;
+ }
+ numbits = numbits - dstoffset;
+ }
+}
+
+/*
+ * Default method to write pixels into a Z image data structure.
+ * The algorithm used is:
+ *
+ * copy the destination bitmap_unit or Zpixel to temp
+ * normalize temp if needed
+ * copy the pixel bits into the temp
+ * renormalize temp if needed
+ * copy the temp back into the destination image data
+ */
+
+static void
+PutImagePixels(
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ register char *src;
+ register char *dst;
+ register unsigned int *iptr;
+ register unsigned int x, y;
+ register char *data;
+ Pixel pixel, px;
+ int nbytes, depth, ibu, ibpp, i;
+
+ data = image->data;
+ iptr = pixelindex;
+ depth = image->depth;
+ if (depth == 1) {
+ ibu = image->bitmap_unit;
+ for (y = 0; y < height; y++) /* how can we trust height */
+ for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
+ pixel = pixels[*iptr];
+ for (i = 0, px = pixel; i < sizeof(unsigned long);
+ i++, px >>= 8)
+ ((unsigned char *) &pixel)[i] = px;
+ src = &data[XYINDEX(x, y, image)];
+ dst = (char *) &px;
+ px = 0;
+ nbytes = ibu >> 3;
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ XYNORMALIZE(&px, image);
+ _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
+ XYNORMALIZE(&px, image);
+ src = (char *) &px;
+ dst = &data[XYINDEX(x, y, image)];
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ }
+ } else {
+ ibpp = image->bits_per_pixel;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = pixels[*iptr];
+ if (depth == 4)
+ pixel &= 0xf;
+ for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
+ px >>= 8)
+ ((unsigned char *) &pixel)[i] = px;
+ src = &data[ZINDEX(x, y, image)];
+ dst = (char *) &px;
+ px = 0;
+ nbytes = (ibpp + 7) >> 3;
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ ZNORMALIZE(&px, image);
+ _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
+ ZNORMALIZE(&px, image);
+ src = (char *) &px;
+ dst = &data[ZINDEX(x, y, image)];
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ }
+ }
+}
+
+/*
+ * write pixels into a 32-bits Z image data structure
+ */
+
+#if !defined(WORD64) && !defined(LONG64)
+/* this item is static but deterministic so let it slide; doesn't
+ * hurt re-entrancy of this library. Note if it is actually const then would
+ * be OK under rules of ANSI-C but probably not C++ which may not
+ * want to allocate space for it.
+ */
+static unsigned long byteorderpixel = MSBFirst << 24;
+
+#endif
+
+/*
+ WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
+ 3.2e code - by default you get the speeded-up version.
+*/
+
+static void
+PutImagePixels32(
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ unsigned char *data;
+ unsigned int *iptr;
+ unsigned int y;
+ Pixel pixel;
+
+#ifdef WITHOUT_SPEEDUPS
+
+ unsigned int x;
+ unsigned char *addr;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+#if !defined(WORD64) && !defined(LONG64)
+ if (*((char *) &byteorderpixel) == image->byte_order) {
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ *((unsigned long *) addr) = pixels[*iptr];
+ }
+ } else
+#endif
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = pixels[*iptr];
+ addr[0] = pixel >> 24;
+ addr[1] = pixel >> 16;
+ addr[2] = pixel >> 8;
+ addr[3] = pixel;
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = pixels[*iptr];
+ addr[0] = pixel;
+ addr[1] = pixel >> 8;
+ addr[2] = pixel >> 16;
+ addr[3] = pixel >> 24;
+ }
+
+#else /* WITHOUT_SPEEDUPS */
+
+ unsigned int bpl = image->bytes_per_line;
+ unsigned char *data_ptr, *max_data;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+#if !defined(WORD64) && !defined(LONG64)
+ if (*((char *) &byteorderpixel) == image->byte_order) {
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + (width << 2);
+
+ while (data_ptr < max_data) {
+ *((unsigned long *) data_ptr) = pixels[*(iptr++)];
+ data_ptr += (1 << 2);
+ }
+ data += bpl;
+ }
+ } else
+#endif
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + (width << 2);
+
+ while (data_ptr < max_data) {
+ pixel = pixels[*(iptr++)];
+
+ *data_ptr++ = pixel >> 24;
+ *data_ptr++ = pixel >> 16;
+ *data_ptr++ = pixel >> 8;
+ *data_ptr++ = pixel;
+
+ }
+ data += bpl;
+ }
+ else
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + (width << 2);
+
+ while (data_ptr < max_data) {
+ pixel = pixels[*(iptr++)];
+
+ *data_ptr++ = pixel;
+ *data_ptr++ = pixel >> 8;
+ *data_ptr++ = pixel >> 16;
+ *data_ptr++ = pixel >> 24;
+ }
+ data += bpl;
+ }
+
+#endif /* WITHOUT_SPEEDUPS */
+}
+
+/*
+ * write pixels into a 16-bits Z image data structure
+ */
+
+static void
+PutImagePixels16(
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ unsigned char *data;
+ unsigned int *iptr;
+ unsigned int y;
+
+#ifdef WITHOUT_SPEEDUPS
+
+ unsigned int x;
+ unsigned char *addr;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ addr[0] = pixels[*iptr] >> 8;
+ addr[1] = pixels[*iptr];
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ addr[0] = pixels[*iptr];
+ addr[1] = pixels[*iptr] >> 8;
+ }
+
+#else /* WITHOUT_SPEEDUPS */
+
+ Pixel pixel;
+
+ unsigned int bpl = image->bytes_per_line;
+ unsigned char *data_ptr, *max_data;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + (width << 1);
+
+ while (data_ptr < max_data) {
+ pixel = pixels[*(iptr++)];
+
+ data_ptr[0] = pixel >> 8;
+ data_ptr[1] = pixel;
+
+ data_ptr += (1 << 1);
+ }
+ data += bpl;
+ }
+ else
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + (width << 1);
+
+ while (data_ptr < max_data) {
+ pixel = pixels[*(iptr++)];
+
+ data_ptr[0] = pixel;
+ data_ptr[1] = pixel >> 8;
+
+ data_ptr += (1 << 1);
+ }
+ data += bpl;
+ }
+
+#endif /* WITHOUT_SPEEDUPS */
+}
+
+/*
+ * write pixels into a 8-bits Z image data structure
+ */
+
+static void
+PutImagePixels8(
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ char *data;
+ unsigned int *iptr;
+ unsigned int y;
+
+#ifdef WITHOUT_SPEEDUPS
+
+ unsigned int x;
+
+ data = image->data;
+ iptr = pixelindex;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++)
+ data[ZINDEX8(x, y, image)] = pixels[*iptr];
+
+#else /* WITHOUT_SPEEDUPS */
+
+ unsigned int bpl = image->bytes_per_line;
+ char *data_ptr, *max_data;
+
+ data = image->data;
+ iptr = pixelindex;
+
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + width;
+
+ while (data_ptr < max_data)
+ *(data_ptr++) = pixels[*(iptr++)];
+
+ data += bpl;
+ }
+
+#endif /* WITHOUT_SPEEDUPS */
+}
+
+/*
+ * write pixels into a 1-bit depth image data structure and **offset null**
+ */
+
+static void
+PutImagePixels1(
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ if (image->byte_order != image->bitmap_bit_order)
+ PutImagePixels(image, width, height, pixelindex, pixels);
+ else {
+ unsigned int *iptr;
+ unsigned int y;
+ char *data;
+
+#ifdef WITHOUT_SPEEDUPS
+
+ unsigned int x;
+
+ data = image->data;
+ iptr = pixelindex;
+ if (image->bitmap_bit_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ if (pixels[*iptr] & 1)
+ data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
+ else
+ data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ if (pixels[*iptr] & 1)
+ data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
+ else
+ data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
+ }
+
+#else /* WITHOUT_SPEEDUPS */
+
+ char value;
+ char *data_ptr, *max_data;
+ int bpl = image->bytes_per_line;
+ int diff, count;
+
+ data = image->data;
+ iptr = pixelindex;
+
+ diff = width & 7;
+ width >>= 3;
+
+ if (image->bitmap_bit_order == MSBFirst)
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + width;
+ while (data_ptr < max_data) {
+ value = 0;
+
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+ value = (value << 1) | (pixels[*(iptr++)] & 1);
+
+ *(data_ptr++) = value;
+ }
+ if (diff) {
+ value = 0;
+ for (count = 0; count < diff; count++) {
+ if (pixels[*(iptr++)] & 1)
+ value |= (0x80 >> count);
+ }
+ *(data_ptr) = value;
+ }
+ data += bpl;
+ }
+ else
+ for (y = 0; y < height; y++) {
+ data_ptr = data;
+ max_data = data_ptr + width;
+ while (data_ptr < max_data) {
+ value = 0;
+ iptr += 8;
+
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+ value = (value << 1) | (pixels[*(--iptr)] & 1);
+
+ iptr += 8;
+ *(data_ptr++) = value;
+ }
+ if (diff) {
+ value = 0;
+ for (count = 0; count < diff; count++) {
+ if (pixels[*(iptr++)] & 1)
+ value |= (1 << count);
+ }
+ *(data_ptr) = value;
+ }
+ data += bpl;
+ }
+
+#endif /* WITHOUT_SPEEDUPS */
+ }
+}
+
+int
+XpmCreatePixmapFromXpmImage(
+ Display *display,
+ Drawable d,
+ XpmImage *image,
+ Pixmap *pixmap_return,
+ Pixmap *shapemask_return,
+ XpmAttributes *attributes)
+{
+ XImage *ximage, *shapeimage;
+ int ErrorStatus;
+
+ /* initialize return values */
+ if (pixmap_return)
+ *pixmap_return = 0;
+ if (shapemask_return)
+ *shapemask_return = 0;
+
+ /* create the ximages */
+ ErrorStatus = XpmCreateImageFromXpmImage(display, image,
+ (pixmap_return ? &ximage : NULL),
+ (shapemask_return ?
+ &shapeimage : NULL),
+ attributes);
+ if (ErrorStatus < 0)
+ return (ErrorStatus);
+
+ /* create the pixmaps and destroy images */
+ if (pixmap_return && ximage) {
+ xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
+ XDestroyImage(ximage);
+ }
+ if (shapemask_return && shapeimage) {
+ xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ XDestroyImage(shapeimage);
+ }
+ return (ErrorStatus);
+}
+
+# else /* AMIGA */
+
+static void
+APutImagePixels (
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ unsigned int *data = pixelindex;
+ unsigned int x, y;
+ unsigned char *array;
+ XImage *tmp_img;
+ BOOL success = FALSE;
+
+ array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
+ if (array != NULL)
+ {
+ tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
+ image->rp->BitMap->Depth);
+ if (tmp_img != NULL)
+ {
+ for (y = 0; y < height; ++y)
+ {
+ for (x = 0; x < width; ++x)
+ array[x] = pixels[*(data++)];
+ WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
+ }
+ FreeXImage (tmp_img);
+ success = TRUE;
+ }
+ XpmFree (array);
+ }
+
+ if (!success)
+ {
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ XPutPixel (image, x, y, pixels[*(data++)]);
+ }
+}
+
+# endif/* AMIGA */
+#else /* FOR_MSW part follows */
+static void
+MSWPutImagePixels(
+ Display *dc,
+ XImage *image,
+ unsigned int width,
+ unsigned int height,
+ unsigned int *pixelindex,
+ Pixel *pixels)
+{
+ unsigned int *data = pixelindex;
+ unsigned int x, y;
+ HBITMAP obm;
+
+ obm = SelectObject(*dc, image->bitmap);
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
+ }
+ }
+ SelectObject(*dc, obm);
+}
+
+#endif /* FOR_MSW */
+
+
+
+#if !defined(FOR_MSW) && !defined(AMIGA)
+
+static int
+PutPixel1(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ register char *src;
+ register char *dst;
+ register int i;
+ Pixel px;
+ int nbytes;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
+ ((unsigned char *)&pixel)[i] = px;
+ src = &ximage->data[XYINDEX(x, y, ximage)];
+ dst = (char *)&px;
+ px = 0;
+ nbytes = ximage->bitmap_unit >> 3;
+ for (i = nbytes; --i >= 0; ) *dst++ = *src++;
+ XYNORMALIZE(&px, ximage);
+ i = ((x + ximage->xoffset) % ximage->bitmap_unit);
+ _putbits ((char *)&pixel, i, 1, (char *)&px);
+ XYNORMALIZE(&px, ximage);
+ src = (char *) &px;
+ dst = &ximage->data[XYINDEX(x, y, ximage)];
+ for (i = nbytes; --i >= 0; )
+ *dst++ = *src++;
+
+ return 1;
+}
+
+static int
+PutPixel(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ register char *src;
+ register char *dst;
+ register int i;
+ Pixel px;
+ unsigned int nbytes, ibpp;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ ibpp = ximage->bits_per_pixel;
+ if (ximage->depth == 4)
+ pixel &= 0xf;
+ for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
+ ((unsigned char *) &pixel)[i] = px;
+ src = &ximage->data[ZINDEX(x, y, ximage)];
+ dst = (char *) &px;
+ px = 0;
+ nbytes = (ibpp + 7) >> 3;
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ ZNORMALIZE(&px, ximage);
+ _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
+ ZNORMALIZE(&px, ximage);
+ src = (char *) &px;
+ dst = &ximage->data[ZINDEX(x, y, ximage)];
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+
+ return 1;
+}
+
+#if !defined(WORD64) && !defined(LONG64)
+static int
+PutPixel32(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ unsigned char *addr;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
+ *((unsigned long *)addr) = pixel;
+ return 1;
+}
+#endif
+
+static int
+PutPixel32MSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ unsigned char *addr;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
+ addr[0] = pixel >> 24;
+ addr[1] = pixel >> 16;
+ addr[2] = pixel >> 8;
+ addr[3] = pixel;
+ return 1;
+}
+
+static int
+PutPixel32LSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ unsigned char *addr;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
+ addr[3] = pixel >> 24;
+ addr[2] = pixel >> 16;
+ addr[1] = pixel >> 8;
+ addr[0] = pixel;
+ return 1;
+}
+
+static int
+PutPixel16MSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ unsigned char *addr;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
+ addr[0] = pixel >> 8;
+ addr[1] = pixel;
+ return 1;
+}
+
+static int
+PutPixel16LSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ unsigned char *addr;
+
+ if(x < 0 || y < 0)
+ return 0;
+
+ addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
+ addr[1] = pixel >> 8;
+ addr[0] = pixel;
+ return 1;
+}
+
+static int
+PutPixel8(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ if(x < 0 || y < 0)
+ return 0;
+
+ ximage->data[ZINDEX8(x, y, ximage)] = pixel;
+ return 1;
+}
+
+static int
+PutPixel1MSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ if(x < 0 || y < 0)
+ return 0;
+
+ if (pixel & 1)
+ ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
+ else
+ ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
+ return 1;
+}
+
+static int
+PutPixel1LSB(
+ register XImage *ximage,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ if(x < 0 || y < 0)
+ return 0;
+
+ if (pixel & 1)
+ ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
+ else
+ ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
+ return 1;
+}
+
+#endif /* not FOR_MSW && not AMIGA */
+
+/*
+ * This function parses an Xpm file or data and directly create an XImage
+ */
+int
+xpmParseDataAndCreate(
+ Display *display,
+ xpmData *data,
+ XImage **image_return,
+ XImage **shapeimage_return,
+ XpmImage *image,
+ XpmInfo *info,
+ XpmAttributes *attributes)
+{
+ /* variables stored in the XpmAttributes structure */
+ Visual *visual;
+ Colormap colormap;
+ unsigned int depth;
+ int bitmap_format;
+ XpmFreeColorsFunc freeColors;
+
+ /* variables to return */
+ XImage *ximage = NULL;
+ XImage *shapeimage = NULL;
+ unsigned int mask_pixel_index = XpmUndefPixel;
+
+ /* calculation variables */
+ Pixel *image_pixels = NULL;
+ Pixel *mask_pixels = NULL;
+ Pixel *alloc_pixels = NULL;
+ Pixel *used_pixels = NULL;
+ unsigned int nalloc_pixels = 0;
+ unsigned int nused_pixels = 0;
+ unsigned int width, height, ncolors, cpp;
+ unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
+ XpmColor *colorTable = NULL;
+ char *hints_cmt = NULL;
+ char *colors_cmt = NULL;
+ char *pixels_cmt = NULL;
+
+ unsigned int cmts;
+ int ErrorStatus;
+ xpmHashTable hashtable;
+
+
+ /* initialize return values */
+ if (image_return)
+ *image_return = NULL;
+ if (shapeimage_return)
+ *shapeimage_return = NULL;
+
+
+ /* retrieve information from the XpmAttributes */
+ if (attributes && (attributes->valuemask & XpmVisual))
+ visual = attributes->visual;
+ else
+ visual = XDefaultVisual(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmColormap))
+ colormap = attributes->colormap;
+ else
+ colormap = XDefaultColormap(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmDepth))
+ depth = attributes->depth;
+ else
+ depth = XDefaultDepth(display, XDefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmBitmapFormat))
+ bitmap_format = attributes->bitmap_format;
+ else
+ bitmap_format = ZPixmap;
+
+ if (attributes && (attributes->valuemask & XpmFreeColors))
+ freeColors = attributes->free_colors;
+ else
+ freeColors = FreeColors;
+
+ cmts = info && (info->valuemask & XpmReturnComments);
+
+ /*
+ * parse the header
+ */
+ ErrorStatus = xpmParseHeader(data);
+ if (ErrorStatus != XpmSuccess)
+ return (ErrorStatus);
+
+ /*
+ * read values
+ */
+ ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
+ &x_hotspot, &y_hotspot, &hotspot,
+ &extensions);
+ if (ErrorStatus != XpmSuccess)
+ return (ErrorStatus);
+
+ /*
+ * store the hints comment line
+ */
+ if (cmts)
+ xpmGetCmt(data, &hints_cmt);
+
+ /*
+ * init the hashtable
+ */
+ if (USE_HASHTABLE) {
+ ErrorStatus = xpmHashTableInit(&hashtable);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ }
+
+ /*
+ * read colors
+ */
+ ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ /*
+ * store the colors comment line
+ */
+ if (cmts)
+ xpmGetCmt(data, &colors_cmt);
+
+ /* malloc pixels index tables */
+ if (ncolors >= UINT_MAX / sizeof(Pixel))
+ RETURN(XpmNoMemory);
+
+ image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
+ if (!image_pixels)
+ RETURN(XpmNoMemory);
+
+ mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
+ if (!mask_pixels)
+ RETURN(XpmNoMemory);
+
+ /* maximum of allocated pixels will be the number of colors */
+ alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
+ if (!alloc_pixels)
+ RETURN(XpmNoMemory);
+
+ /* maximum of allocated pixels will be the number of colors */
+ used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
+ if (!used_pixels)
+ RETURN(XpmNoMemory);
+
+ /* get pixel colors, store them in index tables */
+ ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
+ image_pixels, mask_pixels, &mask_pixel_index,
+ alloc_pixels, &nalloc_pixels, used_pixels,
+ &nused_pixels);
+
+ if (ErrorStatus != XpmSuccess
+ && (ErrorStatus < 0 || (attributes
+ && (attributes->valuemask & XpmExactColors)
+ && attributes->exactColors)))
+ RETURN(ErrorStatus);
+
+ /* now create the ximage */
+ if (image_return) {
+ ErrorStatus = CreateXImage(display, visual, depth,
+ (depth == 1 ? bitmap_format : ZPixmap),
+ width, height, &ximage);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+#if !defined(FOR_MSW) && !defined(AMIGA)
+
+ /*
+ * set the XImage pointer function, to be used with XPutPixel,
+ * to an internal optimized function
+ */
+
+ if (ximage->bits_per_pixel == 8)
+ ximage->f.put_pixel = PutPixel8;
+ else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
+ (ximage->byte_order == ximage->bitmap_bit_order))
+ if (ximage->bitmap_bit_order == MSBFirst)
+ ximage->f.put_pixel = PutPixel1MSB;
+ else
+ ximage->f.put_pixel = PutPixel1LSB;
+ else if (ximage->bits_per_pixel == 16)
+ if (ximage->bitmap_bit_order == MSBFirst)
+ ximage->f.put_pixel = PutPixel16MSB;
+ else
+ ximage->f.put_pixel = PutPixel16LSB;
+ else if (ximage->bits_per_pixel == 32)
+#if !defined(WORD64) && !defined(LONG64)
+ if (*((char *)&byteorderpixel) == ximage->byte_order)
+ ximage->f.put_pixel = PutPixel32;
+ else
+#endif
+ if (ximage->bitmap_bit_order == MSBFirst)
+ ximage->f.put_pixel = PutPixel32MSB;
+ else
+ ximage->f.put_pixel = PutPixel32LSB;
+ else if ((ximage->bits_per_pixel | ximage->depth) == 1)
+ ximage->f.put_pixel = PutPixel1;
+ else
+ ximage->f.put_pixel = PutPixel;
+#endif /* not FOR_MSW && not AMIGA */
+ }
+
+ /* create the shape mask image */
+ if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
+ ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
+ width, height, &shapeimage);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+#if !defined(FOR_MSW) && !defined(AMIGA)
+ if (shapeimage->bitmap_bit_order == MSBFirst)
+ shapeimage->f.put_pixel = PutPixel1MSB;
+ else
+ shapeimage->f.put_pixel = PutPixel1LSB;
+#endif
+ }
+
+ /*
+ * read pixels and put them in the XImage
+ */
+ ErrorStatus = ParseAndPutPixels(
+#ifdef FOR_MSW
+ display,
+#endif
+ data, width, height, ncolors, cpp,
+ colorTable, &hashtable,
+ ximage, image_pixels,
+ shapeimage, mask_pixels);
+ XpmFree(image_pixels);
+ image_pixels = NULL;
+ XpmFree(mask_pixels);
+ mask_pixels = NULL;
+
+ /*
+ * free the hastable
+ */
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ else if (USE_HASHTABLE)
+ xpmHashTableFree(&hashtable);
+
+ /*
+ * store the pixels comment line
+ */
+ if (cmts)
+ xpmGetCmt(data, &pixels_cmt);
+
+ /*
+ * parse extensions
+ */
+ if (info && (info->valuemask & XpmReturnExtensions)) {
+ if (extensions) {
+ ErrorStatus = xpmParseExtensions(data, &info->extensions,
+ &info->nextensions);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ } else {
+ info->extensions = NULL;
+ info->nextensions = 0;
+ }
+ }
+ /*
+ * store found informations in the XpmImage structure
+ */
+ image->width = width;
+ image->height = height;
+ image->cpp = cpp;
+ image->ncolors = ncolors;
+ image->colorTable = colorTable;
+ image->data = NULL;
+
+ if (info) {
+ if (cmts) {
+ info->hints_cmt = hints_cmt;
+ info->colors_cmt = colors_cmt;
+ info->pixels_cmt = pixels_cmt;
+ }
+ if (hotspot) {
+ info->x_hotspot = x_hotspot;
+ info->y_hotspot = y_hotspot;
+ info->valuemask |= XpmHotspot;
+ }
+ }
+ /* if requested return used pixels in the XpmAttributes structure */
+ if (attributes && (attributes->valuemask & XpmReturnPixels ||
+/* 3.2 backward compatibility code */
+ attributes->valuemask & XpmReturnInfos)) {
+/* end 3.2 bc */
+ attributes->pixels = used_pixels;
+ attributes->npixels = nused_pixels;
+ attributes->mask_pixel = mask_pixel_index;
+ } else
+ XpmFree(used_pixels);
+
+ /* if requested return alloc'ed pixels in the XpmAttributes structure */
+ if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
+ attributes->alloc_pixels = alloc_pixels;
+ attributes->nalloc_pixels = nalloc_pixels;
+ } else
+ XpmFree(alloc_pixels);
+
+ /* return created images */
+ if (image_return)
+ *image_return = ximage;
+ if (shapeimage_return)
+ *shapeimage_return = shapeimage;
+
+ return (XpmSuccess);
+
+/* exit point in case of error, free only locally allocated variables */
+error:
+ if (USE_HASHTABLE)
+ xpmHashTableFree(&hashtable);
+ if (colorTable)
+ xpmFreeColorTable(colorTable, ncolors);
+ if (hints_cmt)
+ XpmFree(hints_cmt);
+ if (colors_cmt)
+ XpmFree(colors_cmt);
+ if (pixels_cmt)
+ XpmFree(pixels_cmt);
+ if (ximage)
+ XDestroyImage(ximage);
+ if (shapeimage)
+ XDestroyImage(shapeimage);
+ if (image_pixels)
+ XpmFree(image_pixels);
+ if (mask_pixels)
+ XpmFree(mask_pixels);
+ if (nalloc_pixels)
+ (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
+ if (alloc_pixels)
+ XpmFree(alloc_pixels);
+ if (used_pixels)
+ XpmFree(used_pixels);
+
+ return (ErrorStatus);
+}
+
+static int
+ParseAndPutPixels(
+#ifdef FOR_MSW
+ Display *dc,
+#endif
+ xpmData *data,
+ unsigned int width,
+ unsigned int height,
+ unsigned int ncolors,
+ unsigned int cpp,
+ XpmColor *colorTable,
+ xpmHashTable *hashtable,
+ XImage *image,
+ Pixel *image_pixels,
+ XImage *shapeimage,
+ Pixel *shape_pixels)
+{
+ unsigned int a, x, y;
+
+ switch (cpp) {
+
+ case (1): /* Optimize for single character
+ * colors */
+ {
+ unsigned short colidx[256];
+#ifdef FOR_MSW
+ HDC shapedc;
+ HBITMAP obm, sobm;
+
+ if ( shapeimage ) {
+ shapedc = CreateCompatibleDC(*dc);
+ sobm = SelectObject(shapedc, shapeimage->bitmap);
+ } else {
+ shapedc = NULL;
+ }
+ obm = SelectObject(*dc, image->bitmap);
+#endif
+ if (ncolors > 256)
+ return (XpmFileInvalid);
+
+ bzero((char *)colidx, 256 * sizeof(short));
+ for (a = 0; a < ncolors; a++)
+ colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
+
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++) {
+ int c = xpmGetC(data);
+
+ if (c > 0 && c < 256 && colidx[c] != 0) {
+#ifndef FOR_MSW
+ XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
+ if (shapeimage)
+ XPutPixel(shapeimage, x, y,
+ shape_pixels[colidx[c] - 1]);
+#else
+ SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
+ if (shapedc) {
+ SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
+ }
+#endif
+ } else
+ return (XpmFileInvalid);
+ }
+ }
+#ifdef FOR_MSW
+ if ( shapedc ) {
+ SelectObject(shapedc, sobm);
+ DeleteDC(shapedc);
+ }
+ SelectObject(*dc, obm);
+#endif
+ }
+ break;
+
+ case (2): /* Optimize for double character
+ * colors */
+ {
+
+/* free all allocated pointers at all exits */
+#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
+if (cidx[f]) XpmFree(cidx[f]);}
+
+ /* array of pointers malloced by need */
+ unsigned short *cidx[256];
+ unsigned int char1;
+
+ bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
+ for (a = 0; a < ncolors; a++) {
+ char1 = (unsigned char) colorTable[a].string[0];
+ if (cidx[char1] == NULL) { /* get new memory */
+ cidx[char1] = (unsigned short *)
+ XpmCalloc(256, sizeof(unsigned short));
+ if (cidx[char1] == NULL) { /* new block failed */
+ FREE_CIDX;
+ return (XpmNoMemory);
+ }
+ }
+ cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
+ }
+
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++) {
+ int cc1 = xpmGetC(data);
+ if (cc1 > 0 && cc1 < 256) {
+ int cc2 = xpmGetC(data);
+ if (cc2 > 0 && cc2 < 256 &&
+ cidx[cc1] && cidx[cc1][cc2] != 0) {
+#ifndef FOR_MSW
+ XPutPixel(image, x, y,
+ image_pixels[cidx[cc1][cc2] - 1]);
+ if (shapeimage)
+ XPutPixel(shapeimage, x, y,
+ shape_pixels[cidx[cc1][cc2] - 1]);
+#else
+ SelectObject(*dc, image->bitmap);
+ SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
+ if (shapeimage) {
+ SelectObject(*dc, shapeimage->bitmap);
+ SetPixel(*dc, x, y,
+ shape_pixels[cidx[cc1][cc2] - 1]);
+ }
+#endif
+ } else {
+ FREE_CIDX;
+ return (XpmFileInvalid);
+ }
+ } else {
+ FREE_CIDX;
+ return (XpmFileInvalid);
+ }
+ }
+ }
+ FREE_CIDX;
+ }
+ break;
+
+ default: /* Non-optimized case of long color
+ * names */
+ {
+ char *s;
+ char buf[BUFSIZ];
+
+ if (cpp >= sizeof(buf))
+ return (XpmFileInvalid);
+
+ buf[cpp] = '\0';
+ if (USE_HASHTABLE) {
+ xpmHashAtom *slot;
+
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++) {
+ for (a = 0, s = buf; a < cpp; a++, s++)
+ *s = xpmGetC(data);
+ slot = xpmHashSlot(hashtable, buf);
+ if (!*slot) /* no color matches */
+ return (XpmFileInvalid);
+#ifndef FOR_MSW
+ XPutPixel(image, x, y,
+ image_pixels[HashColorIndex(slot)]);
+ if (shapeimage)
+ XPutPixel(shapeimage, x, y,
+ shape_pixels[HashColorIndex(slot)]);
+#else
+ SelectObject(*dc, image->bitmap);
+ SetPixel(*dc, x, y,
+ image_pixels[HashColorIndex(slot)]);
+ if (shapeimage) {
+ SelectObject(*dc, shapeimage->bitmap);
+ SetPixel(*dc, x, y,
+ shape_pixels[HashColorIndex(slot)]);
+ }
+#endif
+ }
+ }
+ } else {
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++) {
+ for (a = 0, s = buf; a < cpp; a++, s++)
+ *s = xpmGetC(data);
+ for (a = 0; a < ncolors; a++)
+ if (!strcmp(colorTable[a].string, buf))
+ break;
+ if (a == ncolors) /* no color matches */
+ return (XpmFileInvalid);
+#ifndef FOR_MSW
+ XPutPixel(image, x, y, image_pixels[a]);
+ if (shapeimage)
+ XPutPixel(shapeimage, x, y, shape_pixels[a]);
+#else
+ SelectObject(*dc, image->bitmap);
+ SetPixel(*dc, x, y, image_pixels[a]);
+ if (shapeimage) {
+ SelectObject(*dc, shapeimage->bitmap);
+ SetPixel(*dc, x, y, shape_pixels[a]);
+ }
+#endif
+ }
+ }
+ }
+ }
+ break;
+ }
+ return (XpmSuccess);
+}
|