1530 lines
41 KiB
C
1530 lines
41 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
#include "xpmP.h"
|
|
#include <ctype.h>
|
|
#if defined(SYSV) || defined(SVR4) || defined(VMS) || defined(__GNUC__)
|
|
#include <string.h>
|
|
#else
|
|
#include <strings.h>
|
|
#endif
|
|
|
|
LFUNC(xpmVisualType, int, (Visual *visual));
|
|
|
|
#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));
|
|
#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));
|
|
|
|
LFUNC(CreateXImage, int, (Display *display, Visual *visual,
|
|
unsigned int depth, 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
|
|
/* XImage pixel routines */
|
|
LFUNC(SetImagePixels, void, (XImage *image, unsigned int width,
|
|
unsigned int height, unsigned int *pixelindex,
|
|
Pixel *pixels));
|
|
|
|
LFUNC(SetImagePixels32, void, (XImage *image, unsigned int width,
|
|
unsigned int height, unsigned int *pixelindex,
|
|
Pixel *pixels));
|
|
|
|
LFUNC(SetImagePixels16, void, (XImage *image, unsigned int width,
|
|
unsigned int height, unsigned int *pixelindex,
|
|
Pixel *pixels));
|
|
|
|
LFUNC(SetImagePixels8, void, (XImage *image, unsigned int width,
|
|
unsigned int height, unsigned int *pixelindex,
|
|
Pixel *pixels));
|
|
|
|
LFUNC(SetImagePixels1, void, (XImage *image, unsigned int width,
|
|
unsigned int height, unsigned int *pixelindex,
|
|
Pixel *pixels));
|
|
#else /* ndef FOR_MSW */
|
|
/* FOR_MSW pixel routine */
|
|
LFUNC(MSWSetImagePixels, void, (Display *dc, XImage *image,
|
|
unsigned int width, unsigned int height,
|
|
unsigned int *pixelindex, Pixel *pixels));
|
|
#endif /* ndef FOR_MSW */
|
|
|
|
#ifdef NEED_STRCASECMP
|
|
FUNC(strcasecmp, int, (char *s1, char *s2));
|
|
|
|
/*
|
|
* in case strcasecmp is not provided by the system here is one
|
|
* which does the trick
|
|
*/
|
|
int
|
|
strcasecmp(s1, s2)
|
|
register char *s1, *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 *visual;
|
|
{
|
|
#ifndef FOR_MSW
|
|
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
|
|
/* there should be a similar switch for MSW */
|
|
return (XPM_COLOR);
|
|
#endif
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
int cols_index;
|
|
long closeness;
|
|
} CloseColor;
|
|
|
|
static int
|
|
closeness_cmp(a, b)
|
|
Const void *a, *b;
|
|
{
|
|
CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
|
|
|
|
/* cast to int as qsort requires */
|
|
return (int) (x->closeness - y->closeness);
|
|
}
|
|
|
|
#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, colormap, visual, col, image_pixel, mask_pixel,
|
|
alloc_pixels, nalloc_pixels, attributes, cols, ncols)
|
|
Display *display;
|
|
Colormap colormap;
|
|
Visual *visual;
|
|
XColor *col;
|
|
Pixel *image_pixel, *mask_pixel;
|
|
Pixel *alloc_pixels;
|
|
unsigned int *nalloc_pixels;
|
|
XpmAttributes *attributes;
|
|
XColor *cols;
|
|
int ncols;
|
|
{
|
|
|
|
/*
|
|
* 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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/*
|
|
* 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 (XAllocColor(display, colormap, &cols[c])) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* 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 (XAllocColor(display, colormap, col)) {
|
|
*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, colormap, visual, colorname, color_index,
|
|
image_pixel, mask_pixel, mask_pixel_index,
|
|
alloc_pixels, nalloc_pixels, used_pixels, nused_pixels,
|
|
attributes, cols, ncols)
|
|
Display *display;
|
|
Colormap colormap;
|
|
Visual *visual;
|
|
char *colorname;
|
|
unsigned int color_index;
|
|
Pixel *image_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;
|
|
{
|
|
XColor xcolor;
|
|
|
|
if (strcasecmp(colorname, TRANSPARENT_COLOR)) {
|
|
if (!XParseColor(display, colormap, colorname, &xcolor))
|
|
return (1);
|
|
if (!XAllocColor(display, colormap, &xcolor)) {
|
|
#ifndef FOR_MSW
|
|
if (USE_CLOSECOLOR)
|
|
return (SetCloseColor(display, colormap, visual, &xcolor,
|
|
image_pixel, mask_pixel,
|
|
alloc_pixels, nalloc_pixels,
|
|
attributes, cols, ncols));
|
|
else
|
|
#endif /* ndef FOR_MSW */
|
|
return (1);
|
|
} else
|
|
alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
|
|
*image_pixel = xcolor.pixel;
|
|
*mask_pixel = 1;
|
|
used_pixels[(*nused_pixels)++] = xcolor.pixel;
|
|
} else {
|
|
*image_pixel = 0;
|
|
*mask_pixel = 0;
|
|
/* store the color table index */
|
|
*mask_pixel_index = color_index;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
static int
|
|
CreateColors(display, attributes, colors, ncolors, image_pixels, mask_pixels,
|
|
mask_pixel_index, alloc_pixels, nalloc_pixels,
|
|
used_pixels, nused_pixels)
|
|
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;
|
|
unsigned int numsymbols;
|
|
|
|
char *colorname;
|
|
unsigned int color, key;
|
|
Bool pixel_defined;
|
|
XpmColorSymbol *symbol;
|
|
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);
|
|
|
|
#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
|
|
int i;
|
|
|
|
ncols = visual->map_entries;
|
|
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 &&
|
|
!strcasecmp(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))
|
|
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)) {
|
|
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)) {
|
|
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
|
|
&& !strcasecmp(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);
|
|
}
|
|
|
|
|
|
/* function call in case of error, frees only locally allocated variables */
|
|
#undef RETURN
|
|
#define RETURN(status) \
|
|
{ \
|
|
if (ximage) XDestroyImage(ximage); \
|
|
if (shapeimage) XDestroyImage(shapeimage); \
|
|
if (image_pixels) XpmFree(image_pixels); \
|
|
if (mask_pixels) XpmFree(mask_pixels); \
|
|
if (nalloc_pixels) \
|
|
XFreeColors(display, colormap, alloc_pixels, nalloc_pixels, 0); \
|
|
if (alloc_pixels) XpmFree(alloc_pixels); \
|
|
if (used_pixels) XpmFree(used_pixels); \
|
|
return (status); \
|
|
}
|
|
|
|
int
|
|
XpmCreateImageFromXpmImage(display, image,
|
|
image_return, shapeimage_return, attributes)
|
|
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;
|
|
|
|
/* 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));
|
|
|
|
ErrorStatus = XpmSuccess;
|
|
|
|
/* 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,
|
|
image->width, image->height, &ximage);
|
|
if (ErrorStatus != XpmSuccess)
|
|
RETURN(ErrorStatus);
|
|
|
|
#ifndef FOR_MSW
|
|
|
|
/*
|
|
* set the ximage data
|
|
*
|
|
* In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
|
|
* optimized functions, otherwise use slower but sure general one.
|
|
*
|
|
*/
|
|
|
|
if (ximage->depth == 1)
|
|
SetImagePixels1(ximage, image->width, image->height,
|
|
image->data, image_pixels);
|
|
else if (ximage->bits_per_pixel == 8)
|
|
SetImagePixels8(ximage, image->width, image->height,
|
|
image->data, image_pixels);
|
|
else if (ximage->bits_per_pixel == 16)
|
|
SetImagePixels16(ximage, image->width, image->height,
|
|
image->data, image_pixels);
|
|
else if (ximage->bits_per_pixel == 32)
|
|
SetImagePixels32(ximage, image->width, image->height,
|
|
image->data, image_pixels);
|
|
else
|
|
SetImagePixels(ximage, image->width, image->height,
|
|
image->data, image_pixels);
|
|
#else /* FOR_MSW */
|
|
MSWSetImagePixels(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, image->width,
|
|
image->height, &shapeimage);
|
|
if (ErrorStatus != XpmSuccess)
|
|
RETURN(ErrorStatus);
|
|
|
|
#ifndef FOR_MSW
|
|
SetImagePixels1(shapeimage, image->width, image->height,
|
|
image->data, mask_pixels);
|
|
#else
|
|
MSWSetImagePixels(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);
|
|
}
|
|
|
|
|
|
/*
|
|
* Create an XImage
|
|
*/
|
|
static int
|
|
CreateXImage(display, visual, depth, width, height, image_return)
|
|
Display *display;
|
|
Visual *visual;
|
|
unsigned int depth;
|
|
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, ZPixmap, 0, 0,
|
|
width, height, bitmap_pad, 0);
|
|
if (!*image_return)
|
|
return (XpmNoMemory);
|
|
|
|
#ifndef FOR_MSW
|
|
/* now that bytes_per_line must have been set properly alloc data */
|
|
(*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 XCreateImage has done it all */
|
|
#endif
|
|
return (XpmSuccess);
|
|
}
|
|
|
|
#ifndef FOR_MSW
|
|
/*
|
|
* 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 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(bpt, nb)
|
|
register unsigned char *bpt;
|
|
register int nb;
|
|
{
|
|
do {
|
|
*bpt = _reverse_byte[*bpt];
|
|
bpt++;
|
|
} while (--nb > 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void
|
|
xpm_xynormalizeimagebits(bp, img)
|
|
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(bp, img)
|
|
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(src, dstoffset, numbits, dst)
|
|
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
|
|
SetImagePixels(image, width, height, pixelindex, pixels)
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
register char *src;
|
|
register char *dst;
|
|
register unsigned int *iptr;
|
|
register int x, y, i;
|
|
register char *data;
|
|
Pixel pixel, px;
|
|
int nbytes, depth, ibu, ibpp;
|
|
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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 /* constant */ RTXpm_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
|
|
SetImagePixels32(image, width, height, pixelindex, pixels)
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
unsigned char *data;
|
|
unsigned int *iptr;
|
|
int y;
|
|
Pixel pixel;
|
|
|
|
#ifdef WITHOUT_SPEEDUPS
|
|
|
|
int x;
|
|
unsigned char *addr;
|
|
|
|
data = (unsigned char *) image->data;
|
|
iptr = pixelindex;
|
|
#if !defined(WORD64) && !defined(LONG64)
|
|
if (*((char *) &RTXpm_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 */
|
|
|
|
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 *) &RTXpm_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
|
|
SetImagePixels16(image, width, height, pixelindex, pixels)
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
unsigned char *data;
|
|
unsigned int *iptr;
|
|
int y;
|
|
|
|
#ifdef WITHOUT_SPEEDUPS
|
|
|
|
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;
|
|
|
|
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
|
|
SetImagePixels8(image, width, height, pixelindex, pixels)
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
char *data;
|
|
unsigned int *iptr;
|
|
int y;
|
|
|
|
#ifdef WITHOUT_SPEEDUPS
|
|
|
|
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 */
|
|
|
|
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
|
|
SetImagePixels1(image, width, height, pixelindex, pixels)
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
if (image->byte_order != image->bitmap_bit_order)
|
|
SetImagePixels(image, width, height, pixelindex, pixels);
|
|
else {
|
|
unsigned int *iptr;
|
|
int y;
|
|
char *data;
|
|
|
|
#ifdef WITHOUT_SPEEDUPS
|
|
|
|
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, d, image,
|
|
pixmap_return, shapemask_return, attributes)
|
|
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 /* FOR_MSW part follows */
|
|
static void
|
|
MSWSetImagePixels(dc, image, width, height, pixelindex, pixels)
|
|
Display *dc;
|
|
XImage *image;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
unsigned int *pixelindex;
|
|
Pixel *pixels;
|
|
{
|
|
unsigned int *data = pixelindex;
|
|
unsigned int x, y;
|
|
|
|
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] */
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* FOR_MSW */
|