192 lines
5.9 KiB
C
192 lines
5.9 KiB
C
|
/* xpm-ximage.c --- converts XPM data to an XImage for use with OpenGL.*/
|
||
|
|
||
|
#if !defined( lint ) && !defined( SABER )
|
||
|
static const char sccsid[] = "@(#)xpm-ximage.c 5.0 00/11/14 xlockmore";
|
||
|
|
||
|
#endif
|
||
|
/*
|
||
|
* xscreensaver, Copyright (c) 1998 Jamie Zawinski <jwz@jwz.org>
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||
|
* the above copyright notice appear in all copies and that both that
|
||
|
* copyright notice and this permission notice appear in supporting
|
||
|
* documentation. No representations are made about the suitability of this
|
||
|
* software for any purpose. It is provided "as is" without express or
|
||
|
* implied warranty.
|
||
|
*
|
||
|
* Version extracted from xscreensaver 3.26 for xlockmore
|
||
|
* by Eric Lassauge <lassauge AT users.sourceforge.net> http://lassauge.free.fr/linux.html
|
||
|
* Parts of the code are from Jamie, the rest dealing with alpha channel is
|
||
|
* from me.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifdef STANDALONE
|
||
|
#include "xlockmore.h" /* from the xlockmore distribution */
|
||
|
#else /* !STANDALONE */
|
||
|
#include "xlock.h" /* from the xlockmore distribution */
|
||
|
#endif /* !STANDALONE */
|
||
|
|
||
|
#include <X11/Intrinsic.h>
|
||
|
|
||
|
#ifdef HAVE_XPM
|
||
|
#include <X11/xpm.h>
|
||
|
|
||
|
#include <X11/Xutil.h>
|
||
|
|
||
|
static Bool
|
||
|
bigendian (void)
|
||
|
{
|
||
|
union { int i; char c[sizeof(int)]; } u;
|
||
|
u.i = 1;
|
||
|
return !u.c[0];
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Returns an XImage structure containing the bits of the given XPM image.
|
||
|
This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
|
||
|
extra byte set to 0xFF or 0x00 dealing with alpha value.
|
||
|
|
||
|
The Display and Visual arguments are used only for creating the XImage;
|
||
|
no bits are pushed to the server.
|
||
|
|
||
|
The Colormap argument is used just for parsing color names; no colors
|
||
|
are allocated.
|
||
|
*/
|
||
|
XImage *
|
||
|
xpm_to_ximage(Display *dpy, Visual *visual, Colormap cmap, char **xpm_data)
|
||
|
{
|
||
|
/* All we want to do is get RGB data out of the XPM file built in to this
|
||
|
program. This is a pain, because there is no way (as of XPM version
|
||
|
4.6, at least) to get libXpm to make an XImage without also allocating
|
||
|
colors with XAllocColor. So, instead, we create an XpmImage and parse
|
||
|
out the RGB values of the pixels ourselves; and construct an XImage
|
||
|
by hand. Regardless of the depth of the visual we're using, this
|
||
|
XImage will have 32 bits per pixel, 8 each per R, G, and B. We put
|
||
|
0xFF or 0x00 in the fourth slot, as GL will interpret that as "alpha".
|
||
|
Alpha is detected using "None" color of XPM file.
|
||
|
*/
|
||
|
XImage *ximage;
|
||
|
XpmImage xpm_image;
|
||
|
XpmInfo xpm_info;
|
||
|
int result, trans_idx = 0;
|
||
|
int x, y, i;
|
||
|
int bpl, wpl;
|
||
|
XColor colors[256];
|
||
|
|
||
|
memset (&xpm_image, 0, sizeof(xpm_image));
|
||
|
memset (&xpm_info, 0, sizeof(xpm_info));
|
||
|
result = XpmCreateXpmImageFromData (xpm_data, &xpm_image, &xpm_info);
|
||
|
if (result != XpmSuccess)
|
||
|
{
|
||
|
(void) fprintf(stderr, "Unable to parse xpm data (%d).\n",
|
||
|
result);
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
if (xpm_image.ncolors > 256)
|
||
|
{
|
||
|
(void) fprintf(stderr,
|
||
|
"Unable to use xpm data with too much colors (%d).\n",
|
||
|
xpm_image.ncolors);
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
ximage = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0,
|
||
|
xpm_image.width, xpm_image.height, 32, 0);
|
||
|
|
||
|
bpl = ximage->bytes_per_line;
|
||
|
wpl = bpl/4;
|
||
|
|
||
|
if ( (ximage->data = (char *) malloc(xpm_image.height * bpl)) == NULL)
|
||
|
{
|
||
|
/* free everything up to now */
|
||
|
XDestroyImage(ximage);
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
/* Parse the colors in the XPM into RGB values. */
|
||
|
for (i = 0; i < (int) xpm_image.ncolors; i++)
|
||
|
{
|
||
|
/* Before throwing an error, check if it is the "None" color */
|
||
|
if (xpm_image.colorTable[i].c_color &&
|
||
|
(!strncasecmp(xpm_image.colorTable[i].c_color,"none",4)))
|
||
|
{
|
||
|
trans_idx = i;
|
||
|
colors[trans_idx].red = 0xFF;
|
||
|
colors[trans_idx].green = 0xFF;
|
||
|
colors[trans_idx].blue = 0xFF;
|
||
|
}
|
||
|
else if (!XParseColor(dpy, cmap, xpm_image.colorTable[i].c_color,
|
||
|
&colors[i]))
|
||
|
{
|
||
|
(void) fprintf(stderr,"Unparsable color: %s\n",
|
||
|
xpm_image.colorTable[i].c_color);
|
||
|
/* free everything up to now */
|
||
|
free(ximage->data);
|
||
|
XDestroyImage(ximage);
|
||
|
return None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Translate the XpmImage to an RGB XImage. */
|
||
|
{
|
||
|
int rpos, gpos, bpos, apos; /* bitfield positions */
|
||
|
|
||
|
/* Note that unlike X, which is endianness-agnostic (since any XImage
|
||
|
can have its own specific bit ordering, with the server reversing
|
||
|
things as necessary) OpenGL pretends everything is client-side, so
|
||
|
we need to pack things in the right order for the client machine.
|
||
|
*/
|
||
|
if (bigendian())
|
||
|
rpos = 24, gpos = 16, bpos = 8, apos = 0;
|
||
|
else
|
||
|
rpos = 0, gpos = 8, bpos = 16, apos = 24;
|
||
|
|
||
|
for (y = 0; y < (int) xpm_image.height; y++)
|
||
|
{
|
||
|
int y2 = (xpm_image.height-1-y); /* Texture maps are upside down. */
|
||
|
|
||
|
unsigned int *oline = (unsigned int *) (ximage->data + (y * bpl));
|
||
|
unsigned int *iline = (unsigned int *) (xpm_image.data + (y2 * wpl));
|
||
|
|
||
|
for (x = 0; x < (int) xpm_image.width; x++)
|
||
|
{
|
||
|
XColor *c = &colors[iline[x]];
|
||
|
/* Again, check for transparent color */
|
||
|
if ((int) iline[x] == trans_idx)
|
||
|
/* pack it as RGBA transparent */
|
||
|
oline[x] = (((c->red >> 8) << rpos) |
|
||
|
((c->green >> 8) << gpos) |
|
||
|
((c->blue >> 8) << bpos) |
|
||
|
(0x00 << apos));
|
||
|
else
|
||
|
/* pack it as RGBA */
|
||
|
oline[x] = (((c->red >> 8) << rpos) |
|
||
|
((c->green >> 8) << gpos) |
|
||
|
((c->blue >> 8) << bpos) |
|
||
|
(0xFF << apos));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* I sure hope these only free the contents, and not the args. */
|
||
|
XpmFreeXpmImage (&xpm_image);
|
||
|
XpmFreeXpmInfo (&xpm_info);
|
||
|
|
||
|
return ximage;
|
||
|
}
|
||
|
|
||
|
#else /* !HAVE_XPM */
|
||
|
|
||
|
|
||
|
XImage *
|
||
|
xpm_to_ximage(Display *dpy, Visual *visual, Colormap cmap, char **xpm_data)
|
||
|
{
|
||
|
(void) fprintf(stderr, "Not compiled with XPM support.\n");
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
#endif /* !HAVE_XPM */
|