http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.34.tar.gz
[xscreensaver] / utils / logo.c
1 /* xscreensaver, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* XScreenSaver Logo designed by Angela Goodman <rzr_grl@yahoo.com>
13  */
14
15 /* I basically implemented libXPM here, because I don't want the
16    xscreensaver daemon to depend on libXPM for two reasons: first,
17    because I want the logo to show up even if libXPM is not installed
18    on the system; and second, I don't want to have to security-audit
19    libXPM.  The fewer libraries that are linked into the xscreensaver
20    daemon, the more likely to be secure it is.
21  */
22
23 /* If you are looking in here because you're trying to figure out how to
24    change the logo that xscreensaver displays on the splash screen and
25    password dialog, please don't.  The logo is xscreensaver's identity.
26    You wouldn't alter the name or copyright notice on a program that
27    you didn't write; please don't alter its logo either.
28  */
29
30 #include "utils.h"
31 #include "resources.h"
32
33 #include <stdio.h>
34 #include <X11/Xutil.h>
35
36 #include "logo-50.xpm"
37 #include "logo-180.xpm"
38
39 static const char hex[128] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
43                               0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
44                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45                               0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
46                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
47
48 static XImage *
49 parse_xpm_data (Display *dpy, Visual *visual, Colormap colormap, int depth,
50                 unsigned long transparent_color,
51                 unsigned const char * const * data,
52                 int *width_ret, int *height_ret,
53                 unsigned long **pixels_ret, int *npixels_ret,
54                 unsigned char **mask_ret)
55 {
56   int w, w8, h, ncolors, nbytes;
57   char c;
58   int i;
59   struct {
60     char byte;
61     int cr; int cg; int cb;
62     int mr; int mg; int mb;
63   } cmap[256];
64   unsigned char rmap[256];
65
66   unsigned long *pixels;
67   XImage *ximage = 0;
68
69   if (4 != sscanf ((const char *) *data,
70                    "%d %d %d %d %c", &w, &h, &ncolors, &nbytes, &c))
71     abort();
72   if (ncolors < 1 || ncolors > 255)
73     abort();
74   if (nbytes != 1)
75     abort();
76   data++;
77
78   w8 = (w + 8) / 8;
79
80   if (mask_ret)
81     {
82       int s = (w8 * h) + 1;
83       *mask_ret = (unsigned char *) malloc (s);
84       if (!*mask_ret)
85         mask_ret = 0;
86       else
87         memset (*mask_ret, 255, s);
88     }
89
90   for (i = 0; i < ncolors; i++)
91     {
92       const unsigned char *line = *data;
93       cmap[i].byte = *line++;
94       while (*line)
95         {
96           int r, g, b;
97           char which;
98           while (*line == ' ' || *line == '\t')
99             line++;
100           which = *line++;
101           if (which != 'c' && which != 'm')
102             abort();
103           while (*line == ' ' || *line == '\t')
104             line++;
105           if (!strncasecmp(line, "None", 4))
106             {
107               r = g = b = -1;
108               line += 4;
109             }
110           else
111             {
112               if (*line == '#')
113                 line++;
114               r = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
115               g = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
116               b = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
117             }
118
119           if (which == 'c')
120             {
121               cmap[i].cr = r;
122               cmap[i].cg = g;
123               cmap[i].cb = b;
124             }
125           else
126             {
127               cmap[i].mr = r;
128               cmap[i].mg = g;
129               cmap[i].mb = b;
130             }
131         }
132
133       data++;
134     }
135
136   if (depth == 1) transparent_color = 1;
137
138   pixels = (unsigned long *) calloc (ncolors+1, sizeof(*pixels));
139   for (i = 0; i < ncolors; i++)
140     {
141       if (cmap[i].cr == -1) /* transparent */
142         {
143           rmap[(int) cmap[i].byte] = 255;
144         }
145       else
146         {
147           XColor color;
148           color.flags = DoRed|DoGreen|DoBlue;
149           color.red   = (cmap[i].cr << 8) | cmap[i].cr;
150           color.green = (cmap[i].cg << 8) | cmap[i].cg;
151           color.blue  = (cmap[i].cb << 8) | cmap[i].cb;
152           if (depth == 1 ||
153               !XAllocColor (dpy, colormap, &color))
154             {
155               color.pixel = (cmap[i].mr ? 1 : 0);
156             }
157           pixels[i] = color.pixel;
158           rmap[(int) cmap[i].byte] = i;
159         }
160     }
161
162   ximage = XCreateImage (dpy, visual, depth,
163                          (depth == 1 ? XYBitmap : ZPixmap),
164                          0, 0, w, h, 8, 0);
165   if (ximage)
166     {
167       int x, y;
168       ximage->data = (char *)
169         calloc ( ximage->height, ximage->bytes_per_line);
170       for (y = 0; y < h; y++)
171         {
172           const unsigned char *line = *data++;
173           for (x = 0; x < w; x++)
174             {
175               int p = rmap[*line++];
176               XPutPixel (ximage, x, y,
177                          (p == 255 ? transparent_color : pixels[p]));
178
179               if (p == 255 && mask_ret)
180                 (*mask_ret)[(y * w8) + (x >> 3)] &= (~(1 << (x % 8)));
181             }
182         }
183     }
184   
185   *width_ret = w;
186   *height_ret = h;
187   *pixels_ret = pixels;
188   *npixels_ret = ncolors;
189   return ximage;
190 }
191
192
193
194 /* Draws the logo centered in the given Drawable (presumably a Pixmap.)
195    next_frame_p means randomize the flame shape.
196  */
197 Pixmap
198 xscreensaver_logo (Display *dpy, Window window, Colormap cmap,
199                    unsigned long background_color,
200                    unsigned long **pixels_ret, int *npixels_ret,
201                    Pixmap *mask_ret,
202                    Bool big_p)
203 {
204   int npixels, iw, ih;
205   unsigned long *pixels;
206   XImage *image;
207   Pixmap p = 0;
208   XWindowAttributes xgwa;
209   unsigned char *mask = 0;
210
211   XGetWindowAttributes (dpy, window, &xgwa);
212
213   image = parse_xpm_data (dpy, xgwa.visual, xgwa.colormap, xgwa.depth,
214                           background_color,
215                           (big_p ? logo_180_xpm : logo_50_xpm),
216                           &iw, &ih, &pixels, &npixels,
217                           (mask_ret ? &mask : 0));
218   if (image)
219     {
220       XGCValues gcv;
221       GC gc;
222       p = XCreatePixmap (dpy, window, iw, ih, xgwa.depth);
223       gc = XCreateGC (dpy, p, 0, &gcv);
224       XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih);
225       XDestroyImage (image);
226       XFreeGC (dpy, gc);
227
228       if (mask_ret && mask)
229         {
230           *mask_ret = (Pixmap)
231             XCreatePixmapFromBitmapData (dpy, window, (char *) mask,
232                                          iw, ih, 1L, 0L, 1);
233           free (mask);
234         }
235     }
236   return p;
237 }