From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- utils/minixpm.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 utils/minixpm.c (limited to 'utils/minixpm.c') diff --git a/utils/minixpm.c b/utils/minixpm.c new file mode 100644 index 0000000..997e628 --- /dev/null +++ b/utils/minixpm.c @@ -0,0 +1,251 @@ +/* xscreensaver, Copyright (c) 2001-2014 Jamie Zawinski + * + * 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. + */ + +/* I implemented this subset of libXPM here because I don't want the + xscreensaver daemon to depend on libXPM for two reasons: first, + because I want the logo to show up even if libXPM is not installed + on the system; and second, I don't want to have to security-audit + libXPM. The fewer libraries that are linked into the xscreensaver + daemon, the more likely to be secure it is. + + Also, the Cocoa port uses this code since libXPM isn't available + by default on MacOS. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_JWXYZ +# include "jwxyz.h" +#else /* real Xlib */ +# include +# include +#endif /* !HAVE_JWXYZ */ + +#include "minixpm.h" + +extern const char *progname; + +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} + +static const char hex[128] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +XImage * +minixpm_to_ximage (Display *dpy, Visual *visual, Colormap colormap, int depth, + unsigned long transparent_color, + const char * const * data, + int *width_ret, int *height_ret, + unsigned long **pixels_ret, int *npixels_ret, + unsigned char **mask_ret) +{ + int w, w8, h, ncolors, nbytes; + char c; + int x, y, i, pixel_count; + struct { + char byte; + int cr; int cg; int cb; + int mr; int mg; int mb; + } cmap[256]; + unsigned char rmap[256]; + + unsigned long *pixels; + XImage *ximage = 0; + + memset (cmap, 0, sizeof(cmap)); /* avoid warnings */ + + if (4 != sscanf ((const char *) *data, + "%d %d %d %d %c", &w, &h, &ncolors, &nbytes, &c)) { + fprintf (stderr, "%s: unparsable XPM header\n", progname); + abort(); + } + + if (ncolors < 1 || ncolors > 255) { + fprintf (stderr, "%s: XPM: ncolors is %d\n", progname, ncolors); + abort(); + } + if (nbytes != 1) { + fprintf (stderr, "%s: %d-byte XPM files not supported\n", + progname, nbytes); + abort(); + } + data++; + + for (i = 0; i < ncolors; i++) + { + const char *line = *data; + cmap[i].byte = *line++; + while (*line) + { + int r, g, b; + char which; + while (*line == ' ' || *line == '\t') + line++; + which = *line; + if (!which) continue; /* whitespace at end of line */ + line++; + if (which != 'c' && which != 'm') { + fprintf (stderr, "%s: unknown XPM pixel type '%c' in \"%s\"\n", + progname, which, *data); + abort(); + } + while (*line == ' ' || *line == '\t') + line++; + if (!strncasecmp(line, "None", 4)) + { + r = g = b = -1; + line += 4; + } + else if (!strncasecmp(line, "white", 5)) + { + r = g = b = 255; + line += 5; + } + else if (!strncasecmp(line, "black", 5)) + { + r = g = b = 0; + line += 5; + } + else + { + if (*line != '#') { + fprintf (stderr, "%s: unparsable XPM color spec: \"%s\"\n", + progname, line); + abort(); + } + if (*line == '#') + line++; + r = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2; + g = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2; + b = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2; + } + + if (which == 'c') + { + cmap[i].cr = r; + cmap[i].cg = g; + cmap[i].cb = b; + } + else + { + cmap[i].mr = r; + cmap[i].mg = g; + cmap[i].mb = b; + } + } + + data++; + } + + if (depth == 1) transparent_color = 1; + + pixels = (unsigned long *) calloc (ncolors+1, sizeof(*pixels)); + pixel_count = 0; + for (i = 0; i < ncolors; i++) + { + if (cmap[i].cr == -1) /* transparent */ + { + rmap[(int) cmap[i].byte] = 255; + } + else + { + XColor color; + color.flags = DoRed|DoGreen|DoBlue; + color.red = (cmap[i].cr << 8) | cmap[i].cr; + color.green = (cmap[i].cg << 8) | cmap[i].cg; + color.blue = (cmap[i].cb << 8) | cmap[i].cb; + if (depth == 1 || + !XAllocColor (dpy, colormap, &color)) + { + color.red = (cmap[i].mr << 8) | cmap[i].mr; + color.green = (cmap[i].mg << 8) | cmap[i].mg; + color.blue = (cmap[i].mb << 8) | cmap[i].mb; + if (!XAllocColor (dpy, colormap, &color)) { + fprintf (stderr, "%s: unable to allocate XPM color\n", + progname); + abort(); + } + } + pixels[pixel_count] = color.pixel; + rmap[(int) cmap[i].byte] = pixel_count; + pixel_count++; + } + } + + ximage = XCreateImage (dpy, visual, depth, + (depth == 1 ? XYBitmap : ZPixmap), + 0, 0, w, h, 8, 0); + if (! ximage) + { + if (pixels) free (pixels); + return 0; + } + + ximage->bitmap_bit_order = + ximage->byte_order = + (bigendian() ? MSBFirst : LSBFirst); + + ximage->data = (char *) calloc (ximage->height, ximage->bytes_per_line); + if (!ximage->data) + { + XDestroyImage (ximage); + if (pixels) free (pixels); + return 0; + } + + w8 = (w + 7) / 8; + if (mask_ret) + { + int s = (w8 * h) + 1; + *mask_ret = (unsigned char *) malloc (s); + if (!*mask_ret) + mask_ret = 0; + else + memset (*mask_ret, 255, s); + } + + for (y = 0; y < h; y++) + { + const char *line = *data++; + for (x = 0; x < w; x++) + { + int p = rmap[(int) *line]; + line++; + XPutPixel (ximage, x, y, (p == 255 ? transparent_color : pixels[p])); + + if (p == 255 && mask_ret) + (*mask_ret)[(y * w8) + (x >> 3)] &= (~(1 << (x & 7))); + } + } + + *width_ret = w; + *height_ret = h; + *pixels_ret = pixels; + *npixels_ret = pixel_count; + return ximage; +} -- cgit v1.2.3-55-g7522