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 f9823ca6c..7c75a4211 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); +} |