#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
#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
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
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
LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width,
unsigned int height, unsigned int *pixelindex,
Pixel *pixels));
# endif/* AMIGA */
#else
LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
unsigned int width, unsigned int height,
unsigned int *pixelindex, Pixel *pixels));
#endif
#ifdef NEED_STRCASECMP
FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
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
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
return (XPM_COLOR);
# endif
#else
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;
return (int) (x->closeness - y->closeness);
}
static int
AllocColor(
Display *display,
Colormap colormap,
char *colorname,
XColor *xcolor,
void *closure)
{
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
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)
{
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;
#define ITERATIONS 2
for (n = 0; n <= ITERATIONS; ++n) {
CloseColor *closenesses =
(CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
int i, c;
for (i = 0; i < ncols; ++i) {
#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);
}
}
if (n == ITERATIONS)
XUngrabServer(display);
XpmFree(closenesses);
if (i == 0 || i == ncols)
return (1);
if ((*allocColor)(display, colormap, NULL, col, closure)) {
*image_pixel = col->pixel;
*mask_pixel = 1;
alloc_pixels[(*nalloc_pixels)++] = col->pixel;
return (0);
} else {
if (n == ITERATIONS - 1)
XGrabServer(display);
#if 0
if (visual->class == DirectColor) {
} 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
#endif
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)
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
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
*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)
{
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;
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) {
#if 0
if (visual->class == DirectColor) {
} 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
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;
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))
break;
if (!symbol->name && symbol->value) {
int def_index = default_index;
while (defaults[def_index] == NULL)
--def_index;
if (def_index < 2) {
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) {
unsigned int k;
if (colorname) {
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 {
*image_pixels = symbol->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);
}
static int
FreeColors(
Display *display,
Colormap colormap,
Pixel *pixels,
int n,
void *closure)
{
return XFreeColors(display, colormap, pixels, n, 0);
}
#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)
{
Visual *visual;
Colormap colormap;
unsigned int depth;
int bitmap_format;
XpmFreeColorsFunc freeColors;
XImage *ximage = NULL;
XImage *shapeimage = NULL;
unsigned int mask_pixel_index = XpmUndefPixel;
int ErrorStatus;
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;
if (image_return)
*image_return = NULL;
if (shapeimage_return)
*shapeimage_return = NULL;
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);
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);
alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
if (!alloc_pixels)
RETURN(XpmNoMemory);
used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
if (!used_pixels)
RETURN(XpmNoMemory);
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);
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
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
APutImagePixels(ximage, image->width, image->height,
image->data, image_pixels);
# endif
#else
MSWPutImagePixels(display, ximage, image->width, image->height,
image->data, image_pixels);
#endif
}
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
APutImagePixels(shapeimage, image->width, image->height,
image->data, mask_pixels);
# endif
#else
MSWPutImagePixels(display, shapeimage, image->width, image->height,
image->data, mask_pixels);
#endif
}
XpmFree(image_pixels);
XpmFree(mask_pixels);
if (attributes && (attributes->valuemask & XpmReturnPixels ||
attributes->valuemask & XpmReturnInfos)) {
attributes->pixels = used_pixels;
attributes->npixels = nused_pixels;
attributes->mask_pixel = mask_pixel_index;
} else
XpmFree(used_pixels);
if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
attributes->alloc_pixels = alloc_pixels;
attributes->nalloc_pixels = nalloc_pixels;
} else
XpmFree(alloc_pixels);
if (image_return)
*image_return = ximage;
if (shapeimage_return)
*shapeimage_return = shapeimage;
return (ErrorStatus);
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);
}
static int
CreateXImage(
Display *display,
Visual *visual,
unsigned int depth,
int format,
unsigned int width,
unsigned int height,
XImage **image_return)
{
int bitmap_pad;
if (depth > 16)
bitmap_pad = 32;
else if (depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
*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;
}
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
#endif
return (XpmSuccess);
}
#ifndef FOR_MSW
# ifndef AMIGA
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);
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,
int dstoffset,
register int numbits,
register char *dst)
{
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;
}
}
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++)
for (x = 0; x < width; x++, iptr++) {
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++;
}
}
}
#if !defined(WORD64) && !defined(LONG64)
static unsigned long byteorderpixel = MSBFirst << 24;
#endif
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
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
}
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
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
}
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
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
}
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
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
}
}
int
XpmCreatePixmapFromXpmImage(
Display *display,
Drawable d,
XpmImage *image,
Pixmap *pixmap_return,
Pixmap *shapemask_return,
XpmAttributes *attributes)
{
XImage *ximage, *shapeimage;
int ErrorStatus;
if (pixmap_return)
*pixmap_return = 0;
if (shapemask_return)
*shapemask_return = 0;
ErrorStatus = XpmCreateImageFromXpmImage(display, image,
(pixmap_return ? &ximage : NULL),
(shapemask_return ?
&shapeimage : NULL),
attributes);
if (ErrorStatus < 0)
return (ErrorStatus);
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
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
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++)]);
}
}
SelectObject(*dc, obm);
}
#endif
#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
int
xpmParseDataAndCreate(
Display *display,
xpmData *data,
XImage **image_return,
XImage **shapeimage_return,
XpmImage *image,
XpmInfo *info,
XpmAttributes *attributes)
{
Visual *visual;
Colormap colormap;
unsigned int depth;
int bitmap_format;
XpmFreeColorsFunc freeColors;
XImage *ximage = NULL;
XImage *shapeimage = NULL;
unsigned int mask_pixel_index = XpmUndefPixel;
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;
if (image_return)
*image_return = NULL;
if (shapeimage_return)
*shapeimage_return = NULL;
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);
ErrorStatus = xpmParseHeader(data);
if (ErrorStatus != XpmSuccess)
return (ErrorStatus);
ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
&x_hotspot, &y_hotspot, &hotspot,
&extensions);
if (ErrorStatus != XpmSuccess)
return (ErrorStatus);
if (cmts)
xpmGetCmt(data, &hints_cmt);
if (USE_HASHTABLE) {
ErrorStatus = xpmHashTableInit(&hashtable);
if (ErrorStatus != XpmSuccess)
RETURN(ErrorStatus);
}
ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
if (ErrorStatus != XpmSuccess)
RETURN(ErrorStatus);
if (cmts)
xpmGetCmt(data, &colors_cmt);
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);
alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
if (!alloc_pixels)
RETURN(XpmNoMemory);
used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
if (!used_pixels)
RETURN(XpmNoMemory);
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);
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)
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
}
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
}
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;
if (ErrorStatus != XpmSuccess)
RETURN(ErrorStatus);
else if (USE_HASHTABLE)
xpmHashTableFree(&hashtable);
if (cmts)
xpmGetCmt(data, &pixels_cmt);
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;
}
}
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 (attributes && (attributes->valuemask & XpmReturnPixels ||
attributes->valuemask & XpmReturnInfos)) {
attributes->pixels = used_pixels;
attributes->npixels = nused_pixels;
attributes->mask_pixel = mask_pixel_index;
} else
XpmFree(used_pixels);
if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
attributes->alloc_pixels = alloc_pixels;
attributes->nalloc_pixels = nalloc_pixels;
} else
XpmFree(alloc_pixels);
if (image_return)
*image_return = ximage;
if (shapeimage_return)
*shapeimage_return = shapeimage;
return (XpmSuccess);
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):
{
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):
{
#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
if (cidx[f]) XpmFree(cidx[f]);}
unsigned short *cidx[256];
unsigned int char1;
bzero((char *)cidx, 256 * sizeof(unsigned short *));
for (a = 0; a < ncolors; a++) {
char1 = (unsigned char) colorTable[a].string[0];
if (cidx[char1] == NULL) {
cidx[char1] = (unsigned short *)
XpmCalloc(256, sizeof(unsigned short));
if (cidx[char1] == NULL) {
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:
{
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)
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)
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);
}