Blame lib/Xm/Xpmscan.c

Packit b099d7
/* $XConsortium: Xpmscan.c /main/6 1996/09/20 08:16:12 pascale $ */
Packit b099d7
/*
Packit b099d7
 * Copyright (C) 1989-95 GROUPE BULL
Packit b099d7
 *
Packit b099d7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit b099d7
 * of this software and associated documentation files (the "Software"), to
Packit b099d7
 * deal in the Software without restriction, including without limitation the
Packit b099d7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit b099d7
 * sell copies of the Software, and to permit persons to whom the Software is
Packit b099d7
 * furnished to do so, subject to the following conditions:
Packit b099d7
 *
Packit b099d7
 * The above copyright notice and this permission notice shall be included in
Packit b099d7
 * all copies or substantial portions of the Software.
Packit b099d7
 *
Packit b099d7
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit b099d7
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit b099d7
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Packit b099d7
 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit b099d7
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit b099d7
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit b099d7
 *
Packit b099d7
 * Except as contained in this notice, the name of GROUPE BULL shall not be
Packit b099d7
 * used in advertising or otherwise to promote the sale, use or other dealings
Packit b099d7
 * in this Software without prior written authorization from GROUPE BULL.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*****************************************************************************\
Packit b099d7
* scan.c:                                                                     *
Packit b099d7
*                                                                             *
Packit b099d7
*  XPM library                                                                *
Packit b099d7
*  Scanning utility for XPM file format                                       *
Packit b099d7
*                                                                             *
Packit b099d7
*  Developed by Arnaud Le Hors                                                *
Packit b099d7
\*****************************************************************************/
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * The code related to FOR_MSW has been added by
Packit b099d7
 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
Packit b099d7
 */
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
Packit b099d7
Packit b099d7
#include "XpmI.h"
Packit b099d7
Packit b099d7
#define MAXPRINTABLE 92			/* number of printable ascii chars
Packit b099d7
					 * minus \ and " for string compat
Packit b099d7
					 * and ? to avoid ANSI trigraphs. */
Packit b099d7
Packit b099d7
static char *printable =
Packit b099d7
" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
Packit b099d7
ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * printable begin with a space, so in most case, due to my algorithm, when
Packit b099d7
 * the number of different colors is less than MAXPRINTABLE, it will give a
Packit b099d7
 * char follow by "nothing" (a space) in the readable xpm file
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
typedef struct {
Packit b099d7
    Pixel *pixels;
Packit b099d7
    unsigned int *pixelindex;
Packit b099d7
    unsigned int size;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
    unsigned int mask_pixel;		/* whether there is or not */
Packit b099d7
}      PixelsMap;
Packit b099d7
Packit b099d7
LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
Packit b099d7
			unsigned int *index_return));
Packit b099d7
Packit b099d7
LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
Packit b099d7
			    unsigned int *index_return));
Packit b099d7
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
LFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
Packit b099d7
			    unsigned int height, PixelsMap *pmap));
Packit b099d7
Packit b099d7
LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
Packit b099d7
			      unsigned int height, PixelsMap *pmap));
Packit b099d7
Packit b099d7
LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
Packit b099d7
			      unsigned int height, PixelsMap *pmap));
Packit b099d7
Packit b099d7
LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
Packit b099d7
			     unsigned int height, PixelsMap *pmap));
Packit b099d7
Packit b099d7
LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
Packit b099d7
			     unsigned int height, PixelsMap *pmap,
Packit b099d7
			     int (*storeFunc) ()));
Packit b099d7
#else  /* ndef FOR_MSW */
Packit b099d7
LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
Packit b099d7
			       unsigned int height, PixelsMap *pmap,
Packit b099d7
			       int (*storeFunc) ()));
Packit b099d7
#endif
Packit b099d7
LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
Packit b099d7
				  XpmAttributes *attributes));
Packit b099d7
Packit b099d7
LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, 
Packit b099d7
			     unsigned int ncolors, 
Packit b099d7
			     Pixel *pixels, unsigned int mask,
Packit b099d7
			     unsigned int cpp, XpmAttributes *attributes));
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * This function stores the given pixel in the given arrays which are grown
Packit b099d7
 * if not large enough.
Packit b099d7
 */
Packit b099d7
static int
Packit b099d7
storePixel(pixel, pmap, index_return)
Packit b099d7
    Pixel pixel;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
    unsigned int *index_return;
Packit b099d7
{
Packit b099d7
    unsigned int i;
Packit b099d7
    Pixel *p;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
Packit b099d7
    if (*index_return) {		/* this is a transparent pixel! */
Packit b099d7
	*index_return = 0;
Packit b099d7
	return 0;
Packit b099d7
    }
Packit b099d7
    ncolors = pmap->ncolors;
Packit b099d7
    p = pmap->pixels + pmap->mask_pixel;
Packit b099d7
    for (i = pmap->mask_pixel; i < ncolors; i++, p++)
Packit b099d7
	if (*p == pixel)
Packit b099d7
	    break;
Packit b099d7
    if (i == ncolors) {
Packit b099d7
	if (ncolors >= pmap->size) {
Packit b099d7
	    pmap->size *= 2;
Packit b099d7
	    p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
Packit b099d7
	    if (!p)
Packit b099d7
		return (1);
Packit b099d7
	    pmap->pixels = p;
Packit b099d7
Packit b099d7
	}
Packit b099d7
	(pmap->pixels)[ncolors] = pixel;
Packit b099d7
	pmap->ncolors++;
Packit b099d7
    }
Packit b099d7
    *index_return = i;
Packit b099d7
    return 0;
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
storeMaskPixel(pixel, pmap, index_return)
Packit b099d7
    Pixel pixel;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
    unsigned int *index_return;
Packit b099d7
{
Packit b099d7
    if (!pixel) {
Packit b099d7
	if (!pmap->ncolors) {
Packit b099d7
	    pmap->ncolors = 1;
Packit b099d7
	    (pmap->pixels)[0] = 0;
Packit b099d7
	    pmap->mask_pixel = 1;
Packit b099d7
	}
Packit b099d7
	*index_return = 1;
Packit b099d7
    } else
Packit b099d7
	*index_return = 0;
Packit b099d7
    return 0;
Packit b099d7
}
Packit b099d7
Packit b099d7
/* function call in case of error, frees only locally allocated variables */
Packit b099d7
#undef RETURN
Packit b099d7
#define RETURN(status) \
Packit b099d7
do { \
Packit b099d7
    if (pmap.pixelindex) XpmFree(pmap.pixelindex); \
Packit b099d7
    if (pmap.pixels) XpmFree(pmap.pixels); \
Packit b099d7
    if (colorTable) xpmFreeColorTable(colorTable, pmap.ncolors); \
Packit b099d7
    return(status); \
Packit b099d7
} while(0)
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * This function scans the given image and stores the found informations in
Packit b099d7
 * the given XpmImage structure.
Packit b099d7
 */
Packit b099d7
int
Packit b099d7
XpmCreateXpmImageFromImage(display, image, shapeimage,
Packit b099d7
			   xpmimage, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    XImage *image;
Packit b099d7
    XImage *shapeimage;
Packit b099d7
    XpmImage *xpmimage;
Packit b099d7
    XpmAttributes *attributes;
Packit b099d7
{
Packit b099d7
    /* variables stored in the XpmAttributes structure */
Packit b099d7
    unsigned int cpp;
Packit b099d7
Packit b099d7
    /* variables to return */
Packit b099d7
    PixelsMap pmap;
Packit b099d7
    XpmColor *colorTable = NULL;
Packit b099d7
    int ErrorStatus = 0;
Packit b099d7
Packit b099d7
    /* calculation variables */
Packit b099d7
    unsigned int width = 0;
Packit b099d7
    unsigned int height = 0;
Packit b099d7
    unsigned int cppm;			/* minimum chars per pixel */
Packit b099d7
    unsigned int c;
Packit b099d7
Packit b099d7
    /* initialize pmap */
Packit b099d7
    pmap.pixels = NULL;
Packit b099d7
    pmap.pixelindex = NULL;
Packit b099d7
    pmap.size = 256;			/* should be enough most of the time */
Packit b099d7
    pmap.ncolors = 0;
Packit b099d7
    pmap.mask_pixel = 0;
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * get geometry
Packit b099d7
     */
Packit b099d7
    if (image) {
Packit b099d7
	width = image->width;
Packit b099d7
	height = image->height;
Packit b099d7
    } else if (shapeimage) {
Packit b099d7
	width = shapeimage->width;
Packit b099d7
	height = shapeimage->height;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * retrieve information from the XpmAttributes
Packit b099d7
     */
Packit b099d7
    if (attributes && (attributes->valuemask & XpmCharsPerPixel
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
		       || attributes->valuemask & XpmInfos))
Packit b099d7
/* end 3.2 bc */
Packit b099d7
	cpp = attributes->cpp;
Packit b099d7
    else
Packit b099d7
	cpp = 0;
Packit b099d7
Packit b099d7
    if ((height > 0 && width >= UINT_MAX / height) ||
Packit b099d7
	width * height >= UINT_MAX / sizeof(unsigned int))
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    pmap.pixelindex =
Packit b099d7
	(unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
Packit b099d7
    if (!pmap.pixelindex)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    if (pmap.size >= UINT_MAX / sizeof(Pixel)) 
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
Packit b099d7
    if (!pmap.pixels)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * scan shape mask if any
Packit b099d7
     */
Packit b099d7
    if (shapeimage) {
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
	ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
Packit b099d7
				      storeMaskPixel);
Packit b099d7
#else
Packit b099d7
	ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
Packit b099d7
					&pmap, storeMaskPixel);
Packit b099d7
#endif
Packit b099d7
	if (ErrorStatus != XpmSuccess)
Packit b099d7
	    RETURN(ErrorStatus);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * scan the image data
Packit b099d7
     * 
Packit b099d7
     * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
Packit b099d7
     * functions, otherwise use slower but sure general one.
Packit b099d7
     * 
Packit b099d7
     */
Packit b099d7
Packit b099d7
    if (image) {
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
	if (((image->bits_per_pixel | image->depth) == 1)  &&
Packit b099d7
	    (image->byte_order == image->bitmap_bit_order))
Packit b099d7
	    ErrorStatus = GetImagePixels1(image, width, height, &pmap,
Packit b099d7
					  storePixel);
Packit b099d7
	else if (image->format == ZPixmap) {
Packit b099d7
	    if (image->bits_per_pixel == 8)
Packit b099d7
		ErrorStatus = GetImagePixels8(image, width, height, &pmap);
Packit b099d7
	    else if (image->bits_per_pixel == 16)
Packit b099d7
		ErrorStatus = GetImagePixels16(image, width, height, &pmap);
Packit b099d7
	    else if (image->bits_per_pixel == 32)
Packit b099d7
		ErrorStatus = GetImagePixels32(image, width, height, &pmap);
Packit b099d7
	} else
Packit b099d7
	    ErrorStatus = GetImagePixels(image, width, height, &pmap);
Packit b099d7
#else					/* FOR_MSW */
Packit b099d7
	ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
Packit b099d7
					storePixel);
Packit b099d7
#endif
Packit b099d7
	if (ErrorStatus != XpmSuccess)
Packit b099d7
	    RETURN(ErrorStatus);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * get rgb values and a string of char, and possibly a name for each
Packit b099d7
     * color
Packit b099d7
     */
Packit b099d7
    if (pmap.ncolors >= UINT_MAX / sizeof(XpmColor))
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
Packit b099d7
    if (!colorTable)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    /* compute the minimal cpp */
Packit b099d7
    for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
Packit b099d7
	c *= MAXPRINTABLE;
Packit b099d7
    if (cpp < cppm)
Packit b099d7
	cpp = cppm;
Packit b099d7
Packit b099d7
    if (pmap.mask_pixel) {
Packit b099d7
	ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
Packit b099d7
	if (ErrorStatus != XpmSuccess)
Packit b099d7
	    RETURN(ErrorStatus);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
Packit b099d7
				  pmap.pixels, pmap.mask_pixel, cpp,
Packit b099d7
				  attributes);
Packit b099d7
    if (ErrorStatus != XpmSuccess)
Packit b099d7
	RETURN(ErrorStatus);
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * store found informations in the XpmImage structure
Packit b099d7
     */
Packit b099d7
    xpmimage->width = width;
Packit b099d7
    xpmimage->height = height;
Packit b099d7
    xpmimage->cpp = cpp;
Packit b099d7
    xpmimage->ncolors = pmap.ncolors;
Packit b099d7
    xpmimage->colorTable = colorTable;
Packit b099d7
    xpmimage->data = pmap.pixelindex;
Packit b099d7
Packit b099d7
    XpmFree(pmap.pixels);
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
ScanTransparentColor(color, cpp, attributes)
Packit b099d7
    XpmColor *color;
Packit b099d7
    unsigned int cpp;
Packit b099d7
    XpmAttributes *attributes;
Packit b099d7
{
Packit b099d7
    char *s;
Packit b099d7
    unsigned int a, b, c;
Packit b099d7
Packit b099d7
    /* first get a character string */
Packit b099d7
    a = 0;
Packit b099d7
    if (cpp >= UINT_MAX - 1)
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
    if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
    *s++ = printable[c = a % MAXPRINTABLE];
Packit b099d7
    for (b = 1; b < cpp; b++, s++)
Packit b099d7
	*s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
Packit b099d7
    *s = '\0';
Packit b099d7
Packit b099d7
    /* then retreive related info from the attributes if any */
Packit b099d7
    if (attributes && (attributes->valuemask & XpmColorTable
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
		       || attributes->valuemask & XpmInfos)
Packit b099d7
/* end 3.2 bc */
Packit b099d7
	&& attributes->mask_pixel != XpmUndefPixel) {
Packit b099d7
Packit b099d7
	unsigned int key;
Packit b099d7
	char **defaults = (char **) color;
Packit b099d7
	char **mask_defaults;
Packit b099d7
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
	if (attributes->valuemask & XpmColorTable)
Packit b099d7
/* end 3.2 bc */
Packit b099d7
	    mask_defaults = (char **) (
Packit b099d7
		attributes->colorTable + attributes->mask_pixel);
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
	else
Packit b099d7
	    mask_defaults = (char **)
Packit b099d7
		((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
Packit b099d7
/* end 3.2 bc */
Packit b099d7
	for (key = 1; key <= NKEYS; key++) {
Packit b099d7
	    if ((s = mask_defaults[key])) {
Packit b099d7
		defaults[key] = (char *) xpmstrdup(s);
Packit b099d7
		if (!defaults[key])
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    } else {
Packit b099d7
	color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
Packit b099d7
	if (!color->c_color)
Packit b099d7
	    return (XpmNoMemory);
Packit b099d7
    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
ScanOtherColors(display, colors, ncolors, pixels, mask, cpp, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    XpmColor *colors;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
    Pixel *pixels;
Packit b099d7
    unsigned int mask;
Packit b099d7
    unsigned int cpp;
Packit b099d7
    XpmAttributes *attributes;
Packit b099d7
{
Packit b099d7
    /* variables stored in the XpmAttributes structure */
Packit b099d7
    Colormap colormap;
Packit b099d7
    char *rgb_fname;
Packit b099d7
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
    xpmRgbName rgbn[MAX_RGBNAMES];
Packit b099d7
#else
Packit b099d7
    xpmRgbName *rgbn = NULL; 
Packit b099d7
#endif    
Packit b099d7
    int rgbn_max = 0;
Packit b099d7
    unsigned int i, j, c, i2;
Packit b099d7
    XpmColor *color;
Packit b099d7
    XColor *xcolors = NULL, *xcolor;
Packit b099d7
    char *colorname, *s;
Packit b099d7
    XpmColor *colorTable = NULL, **oldColorTable = NULL;
Packit b099d7
    unsigned int ancolors = 0;
Packit b099d7
    Pixel *apixels = NULL;
Packit b099d7
    unsigned int mask_pixel = 0;
Packit b099d7
    Bool found;
Packit b099d7
Packit b099d7
    /* retrieve information from the XpmAttributes */
Packit b099d7
    if (attributes && (attributes->valuemask & XpmColormap))
Packit b099d7
	colormap = attributes->colormap;
Packit b099d7
    else
Packit b099d7
	colormap = XDefaultColormap(display, XDefaultScreen(display));
Packit b099d7
    if (attributes && (attributes->valuemask & XpmRgbFilename))
Packit b099d7
	rgb_fname = attributes->rgb_fname;
Packit b099d7
    else
Packit b099d7
	rgb_fname = NULL;
Packit b099d7
Packit b099d7
    /* start from the right element */
Packit b099d7
    if (mask) {
Packit b099d7
	colors++;
Packit b099d7
	ncolors--;
Packit b099d7
	pixels++;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* first get character strings and rgb values */
Packit b099d7
    if (ncolors >= UINT_MAX / sizeof(XColor) || cpp >= UINT_MAX - 1)
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
    xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
Packit b099d7
    if (!xcolors)
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
Packit b099d7
    for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
Packit b099d7
	 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
Packit b099d7
Packit b099d7
	if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
Packit b099d7
	    XpmFree(xcolors);
Packit b099d7
	    return (XpmNoMemory);
Packit b099d7
	}
Packit b099d7
	*s++ = printable[c = i2 % MAXPRINTABLE];
Packit b099d7
	for (j = 1; j < cpp; j++, s++)
Packit b099d7
	    *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
Packit b099d7
	*s = '\0';
Packit b099d7
Packit b099d7
	xcolor->pixel = *pixels;
Packit b099d7
    }
Packit b099d7
    XQueryColors(display, colormap, xcolors, ncolors);
Packit b099d7
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
    /* read the rgb file if any was specified */
Packit b099d7
    if (rgb_fname)
Packit b099d7
	rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
Packit b099d7
#else
Packit b099d7
    /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
Packit b099d7
    rgbn_max = xpmReadRgbNames(NULL, NULL);
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    if (attributes && attributes->valuemask & XpmColorTable) {
Packit b099d7
	colorTable = attributes->colorTable;
Packit b099d7
	ancolors = attributes->ncolors;
Packit b099d7
	apixels = attributes->pixels;
Packit b099d7
	mask_pixel = attributes->mask_pixel;
Packit b099d7
    }
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
    else if (attributes && attributes->valuemask & XpmInfos) {
Packit b099d7
	oldColorTable = (XpmColor **) attributes->colorTable;
Packit b099d7
	ancolors = attributes->ncolors;
Packit b099d7
	apixels = attributes->pixels;
Packit b099d7
	mask_pixel = attributes->mask_pixel;
Packit b099d7
    }
Packit b099d7
/* end 3.2 bc */
Packit b099d7
Packit b099d7
    for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
Packit b099d7
						  i++, color++, xcolor++) {
Packit b099d7
Packit b099d7
	/* look for related info from the attributes if any */
Packit b099d7
	found = False;
Packit b099d7
	if (ancolors) {
Packit b099d7
	    unsigned int offset = 0;
Packit b099d7
Packit b099d7
	    for (j = 0; j < ancolors; j++) {
Packit b099d7
		if (j == mask_pixel) {
Packit b099d7
		    offset = 1;
Packit b099d7
		    continue;
Packit b099d7
		}
Packit b099d7
		if (apixels[j - offset] == xcolor->pixel)
Packit b099d7
		    break;
Packit b099d7
	    }
Packit b099d7
	    if (j != ancolors) {
Packit b099d7
		unsigned int key;
Packit b099d7
		char **defaults = (char **) color;
Packit b099d7
		char **adefaults;
Packit b099d7
Packit b099d7
/* 3.2 backward compatibility code */
Packit b099d7
		if (oldColorTable)
Packit b099d7
		    adefaults = (char **) oldColorTable[j];
Packit b099d7
		else
Packit b099d7
/* end 3.2 bc */
Packit b099d7
		    adefaults = (char **) (colorTable + j);
Packit b099d7
Packit b099d7
		found = True;
Packit b099d7
		for (key = 1; key <= NKEYS; key++) {
Packit b099d7
		    if ((s = adefaults[key]))
Packit b099d7
			defaults[key] = (char *) xpmstrdup(s);
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
	if (!found) {
Packit b099d7
	    /* if nothing found look for a color name */
Packit b099d7
	    colorname = NULL;
Packit b099d7
	    if (rgbn_max)
Packit b099d7
		colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
Packit b099d7
					  xcolor->green, xcolor->blue);
Packit b099d7
	    if (colorname)
Packit b099d7
		color->c_color = (char *) xpmstrdup(colorname);
Packit b099d7
	    else {
Packit b099d7
		/* at last store the rgb value */
Packit b099d7
		char buf[BUFSIZ];
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
		sprintf(buf, "#%04X%04X%04X",
Packit b099d7
			xcolor->red, xcolor->green, xcolor->blue);
Packit b099d7
#else   
Packit b099d7
		sprintf(buf, "#%02x%02x%02x",
Packit b099d7
			xcolor->red, xcolor->green, xcolor->blue);
Packit b099d7
#endif			
Packit b099d7
		color->c_color = (char *) xpmstrdup(buf);
Packit b099d7
	    }
Packit b099d7
	    if (!color->c_color) {
Packit b099d7
		XpmFree(xcolors);
Packit b099d7
		xpmFreeRgbNames(rgbn, rgbn_max);
Packit b099d7
		return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
    XpmFree(xcolors);
Packit b099d7
    xpmFreeRgbNames(rgbn, rgbn_max);
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
/*
Packit b099d7
 * The functions below are written from X11R5 MIT's code (XImUtil.c)
Packit b099d7
 *
Packit b099d7
 * The idea is to have faster functions than the standard XGetPixel function
Packit b099d7
 * to scan the image data. Indeed we can speed up things by suppressing tests
Packit b099d7
 * performed for each pixel. We do exactly the same tests but at the image
Packit b099d7
 * level.
Packit b099d7
 */
Packit b099d7
Packit b099d7
static unsigned long Const low_bits_table[] = {
Packit b099d7
    0x00000000, 0x00000001, 0x00000003, 0x00000007,
Packit b099d7
    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
Packit b099d7
    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
Packit b099d7
    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
Packit b099d7
    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
Packit b099d7
    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
Packit b099d7
    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
Packit b099d7
    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
Packit b099d7
    0xffffffff
Packit b099d7
};
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Default method to scan pixels of an image data structure.
Packit b099d7
 * The algorithm used is:
Packit b099d7
 *
Packit b099d7
 *	copy the source bitmap_unit or Zpixel into temp
Packit b099d7
 *	normalize temp if needed
Packit b099d7
 *	extract the pixel bits into return value
Packit b099d7
 *
Packit b099d7
 */
Packit b099d7
Packit b099d7
static int
Packit b099d7
GetImagePixels(image, width, height, pmap)
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
{
Packit b099d7
    char *src;
Packit b099d7
    char *dst;
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    char *data;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    int bits, depth, ibu, ibpp, offset, i;
Packit b099d7
    unsigned long lbt;
Packit b099d7
    Pixel pixel, px;
Packit b099d7
Packit b099d7
    data = image->data;
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
    depth = image->depth;
Packit b099d7
    lbt = low_bits_table[depth];
Packit b099d7
    ibpp = image->bits_per_pixel;
Packit b099d7
    offset = image->xoffset;
Packit b099d7
Packit b099d7
    if (image->bitmap_unit < 0)
Packit b099d7
        return (XpmNoMemory);
Packit b099d7
Packit b099d7
    if ((image->bits_per_pixel | image->depth) == 1) {
Packit b099d7
	ibu = image->bitmap_unit;
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		src = &data[XYINDEX(x, y, image)];
Packit b099d7
		dst = (char *) &pixel;
Packit b099d7
		pixel = 0;
Packit b099d7
		for (i = ibu >> 3; --i >= 0;)
Packit b099d7
		    *dst++ = *src++;
Packit b099d7
		XYNORMALIZE(&pixel, image);
Packit b099d7
		bits = (x + offset) % ibu;
Packit b099d7
		pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
Packit b099d7
		if (ibpp != depth)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    } else if (image->format == XYPixmap) {
Packit b099d7
	int nbytes, bpl, j;
Packit b099d7
	long plane = 0;
Packit b099d7
	ibu = image->bitmap_unit;
Packit b099d7
	nbytes = ibu >> 3;
Packit b099d7
	bpl = image->bytes_per_line;
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		pixel = 0;
Packit b099d7
		plane = 0;
Packit b099d7
		for (i = depth; --i >= 0;) {
Packit b099d7
		    src = &data[XYINDEX(x, y, image) + plane];
Packit b099d7
		    dst = (char *) &px;
Packit b099d7
		    px = 0;
Packit b099d7
		    for (j = nbytes; --j >= 0;)
Packit b099d7
			*dst++ = *src++;
Packit b099d7
		    XYNORMALIZE(&px, image);
Packit b099d7
		    bits = (x + offset) % ibu;
Packit b099d7
		    pixel = (pixel << 1) |
Packit b099d7
			    (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
Packit b099d7
		    plane = plane + (bpl * height);
Packit b099d7
		}
Packit b099d7
		if (ibpp != depth)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    } else if (image->format == ZPixmap) {
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		src = &data[ZINDEX(x, y, image)];
Packit b099d7
		dst = (char *) &px;
Packit b099d7
		px = 0;
Packit b099d7
		for (i = (ibpp + 7) >> 3; --i >= 0;)
Packit b099d7
		    *dst++ = *src++;
Packit b099d7
		ZNORMALIZE(&px, image);
Packit b099d7
		pixel = 0;
Packit b099d7
		for (i = sizeof(unsigned long); --i >= 0;)
Packit b099d7
		    pixel = (pixel << 8) | ((unsigned char *) &px)[i];
Packit b099d7
		if (ibpp == 4) {
Packit b099d7
		    if (x & 1)
Packit b099d7
			pixel >>= 4;
Packit b099d7
		    else
Packit b099d7
			pixel &= 0xf;
Packit b099d7
		}
Packit b099d7
		if (ibpp != depth)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    } else
Packit b099d7
	return (XpmColorError); /* actually a bad image */
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * scan pixels of a 32-bits Z image data structure
Packit b099d7
 */
Packit b099d7
Packit b099d7
#if !defined(WORD64) && !defined(LONG64)
Packit b099d7
static unsigned long byteorderpixel = MSBFirst << 24;
Packit b099d7
#endif
Packit b099d7
Packit b099d7
static int
Packit b099d7
GetImagePixels32(image, width, height, pmap)
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
{
Packit b099d7
    unsigned char *addr;
Packit b099d7
    unsigned char *data;
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    unsigned long lbt;
Packit b099d7
    Pixel pixel;
Packit b099d7
    int depth;
Packit b099d7
Packit b099d7
    data = (unsigned char *) image->data;
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
    depth = image->depth;
Packit b099d7
    lbt = low_bits_table[depth];
Packit b099d7
#if !defined(WORD64) && !defined(LONG64)
Packit b099d7
    if (*((char *) &byteorderpixel) == image->byte_order) {
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		addr = &data[ZINDEX32(x, y, image)];
Packit b099d7
		pixel = *((unsigned long *) addr);
Packit b099d7
		if (depth != 32)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    } else
Packit b099d7
#endif
Packit b099d7
    if (image->byte_order == MSBFirst)
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		addr = &data[ZINDEX32(x, y, image)];
Packit b099d7
		pixel = ((unsigned long) addr[0] << 24 |
Packit b099d7
			 (unsigned long) addr[1] << 16 |
Packit b099d7
			 (unsigned long) addr[2] << 8 |
Packit b099d7
			 addr[4]);
Packit b099d7
		if (depth != 32)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    else
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		addr = &data[ZINDEX32(x, y, image)];
Packit b099d7
		pixel = (addr[0] |
Packit b099d7
			 (unsigned long) addr[1] << 8 |
Packit b099d7
			 (unsigned long) addr[2] << 16 |
Packit b099d7
			 (unsigned long) addr[3] << 24);
Packit b099d7
		if (depth != 32)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * scan pixels of a 16-bits Z image data structure
Packit b099d7
 */
Packit b099d7
Packit b099d7
static int
Packit b099d7
GetImagePixels16(image, width, height, pmap)
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
{
Packit b099d7
    unsigned char *addr;
Packit b099d7
    unsigned char *data;
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    unsigned long lbt;
Packit b099d7
    Pixel pixel;
Packit b099d7
    int depth;
Packit b099d7
Packit b099d7
    data = (unsigned char *) image->data;
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
    depth = image->depth;
Packit b099d7
    lbt = low_bits_table[depth];
Packit b099d7
    if (image->byte_order == MSBFirst)
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		addr = &data[ZINDEX16(x, y, image)];
Packit b099d7
		pixel = addr[0] << 8 | addr[1];
Packit b099d7
		if (depth != 16)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    else
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		addr = &data[ZINDEX16(x, y, image)];
Packit b099d7
		pixel = addr[0] | addr[1] << 8;
Packit b099d7
		if (depth != 16)
Packit b099d7
		    pixel &= lbt;
Packit b099d7
		if (storePixel(pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * scan pixels of a 8-bits Z image data structure
Packit b099d7
 */
Packit b099d7
Packit b099d7
static int
Packit b099d7
GetImagePixels8(image, width, height, pmap)
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
{
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    unsigned char *data;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    unsigned long lbt;
Packit b099d7
    Pixel pixel;
Packit b099d7
    int depth;
Packit b099d7
Packit b099d7
    data = (unsigned char *) image->data;
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
    depth = image->depth;
Packit b099d7
    lbt = low_bits_table[depth];
Packit b099d7
    for (y = 0; y < height; y++)
Packit b099d7
	for (x = 0; x < width; x++, iptr++) {
Packit b099d7
	    pixel = data[ZINDEX8(x, y, image)];
Packit b099d7
	    if (depth != 8)
Packit b099d7
		pixel &= lbt;
Packit b099d7
	    if (storePixel(pixel, pmap, iptr))
Packit b099d7
		return (XpmNoMemory);
Packit b099d7
	}
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * scan pixels of a 1-bit depth Z image data structure
Packit b099d7
 */
Packit b099d7
Packit b099d7
static int
Packit b099d7
GetImagePixels1(image, width, height, pmap, storeFunc)
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
    int (*storeFunc) ();
Packit b099d7
{
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    char *data;
Packit b099d7
    Pixel pixel;
Packit b099d7
    int xoff, yoff, offset, bpl;
Packit b099d7
Packit b099d7
    data = image->data;
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
    offset = image->xoffset;
Packit b099d7
    bpl = image->bytes_per_line;
Packit b099d7
Packit b099d7
    if (image->bitmap_bit_order == MSBFirst)
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		xoff = x + offset;
Packit b099d7
		yoff = y * bpl + (xoff >> 3);
Packit b099d7
		xoff &= 7;
Packit b099d7
		pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
Packit b099d7
		if ((*storeFunc) (pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    else
Packit b099d7
	for (y = 0; y < height; y++)
Packit b099d7
	    for (x = 0; x < width; x++, iptr++) {
Packit b099d7
		xoff = x + offset;
Packit b099d7
		yoff = y * bpl + (xoff >> 3);
Packit b099d7
		xoff &= 7;
Packit b099d7
		pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
Packit b099d7
		if ((*storeFunc) (pixel, pmap, iptr))
Packit b099d7
		    return (XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
#else  /* ndef FOR_MSW */
Packit b099d7
static int
Packit b099d7
MSWGetImagePixels(display, image, width, height, pmap, storeFunc)
Packit b099d7
    Display *display;
Packit b099d7
    XImage *image;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    PixelsMap *pmap;
Packit b099d7
    int (*storeFunc) ();
Packit b099d7
{
Packit b099d7
    unsigned int *iptr;
Packit b099d7
    unsigned int x, y;
Packit b099d7
    Pixel pixel;
Packit b099d7
Packit b099d7
    iptr = pmap->pixelindex;
Packit b099d7
Packit b099d7
    SelectObject(*display, image->bitmap);
Packit b099d7
    for (y = 0; y < height; y++) {
Packit b099d7
	for (x = 0; x < width; x++, iptr++) {
Packit b099d7
	    pixel = GetPixel(*display, x, y);
Packit b099d7
	    if ((*storeFunc) (pixel, pmap, iptr))
Packit b099d7
		return (XpmNoMemory);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
#endif
Packit b099d7
Packit b099d7
#ifndef FOR_MSW
Packit b099d7
int
Packit b099d7
XpmCreateXpmImageFromPixmap(display, pixmap, shapemask,
Packit b099d7
			    xpmimage, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    Pixmap pixmap;
Packit b099d7
    Pixmap shapemask;
Packit b099d7
    XpmImage *xpmimage;
Packit b099d7
    XpmAttributes *attributes;
Packit b099d7
{
Packit b099d7
    XImage *ximage = NULL;
Packit b099d7
    XImage *shapeimage = NULL;
Packit b099d7
    unsigned int width = 0;
Packit b099d7
    unsigned int height = 0;
Packit b099d7
    int ErrorStatus;
Packit b099d7
Packit b099d7
    /* get geometry */
Packit b099d7
    if (attributes && attributes->valuemask & XpmSize) {
Packit b099d7
	width = attributes->width;
Packit b099d7
	height = attributes->height;
Packit b099d7
    }
Packit b099d7
    /* get the ximages */
Packit b099d7
    if (pixmap)
Packit b099d7
	xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
Packit b099d7
    if (shapemask)
Packit b099d7
	xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
Packit b099d7
				 &width, &height);
Packit b099d7
Packit b099d7
    /* create the related XpmImage */
Packit b099d7
    ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
Packit b099d7
					     xpmimage, attributes);
Packit b099d7
Packit b099d7
    /* destroy the ximages */
Packit b099d7
    if (ximage)
Packit b099d7
	XDestroyImage(ximage);
Packit b099d7
    if (shapeimage)
Packit b099d7
	XDestroyImage(shapeimage);
Packit b099d7
Packit b099d7
    return (ErrorStatus);
Packit b099d7
}
Packit b099d7
Packit b099d7
#endif /* ndef FOR_MSW */