http://svn.poeml.de/viewvc/ppc/src-unpacked/xscreensaver/xscreensaver-4.12.tar.bz2...
[xscreensaver] / utils / logo.c
1 /* xscreensaver, Copyright (c) 2001-2002, 2003 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 #include "visual.h"
33
34 #include <stdio.h>
35 #include <X11/Xutil.h>
36
37 #include "images/logo-50.xpm"
38 #include "images/logo-180.xpm"
39
40 static const char hex[128] = {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
44                               0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
45                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46                               0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
47                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
48
49 static XImage *
50 parse_xpm_data (Display *dpy, Visual *visual, Colormap colormap, int depth,
51                 unsigned long transparent_color,
52                 const char * const * data,
53                 int *width_ret, int *height_ret,
54                 unsigned long **pixels_ret, int *npixels_ret,
55                 unsigned char **mask_ret)
56 {
57   int w, w8, h, ncolors, nbytes;
58   char c;
59   int i, pixel_count;
60   struct {
61     char byte;
62     int cr; int cg; int cb;
63     int mr; int mg; int mb;
64   } cmap[256];
65   unsigned char rmap[256];
66
67   unsigned long *pixels;
68   XImage *ximage = 0;
69
70   if (4 != sscanf ((const char *) *data,
71                    "%d %d %d %d %c", &w, &h, &ncolors, &nbytes, &c))
72     abort();
73   if (ncolors < 1 || ncolors > 255)
74     abort();
75   if (nbytes != 1)
76     abort();
77   data++;
78
79   w8 = (w + 8) / 8;
80
81   if (mask_ret)
82     {
83       int s = (w8 * h) + 1;
84       *mask_ret = (unsigned char *) malloc (s);
85       if (!*mask_ret)
86         mask_ret = 0;
87       else
88         memset (*mask_ret, 255, s);
89     }
90
91   for (i = 0; i < ncolors; i++)
92     {
93       const char *line = *data;
94       cmap[i].byte = *line++;
95       while (*line)
96         {
97           int r, g, b;
98           char which;
99           while (*line == ' ' || *line == '\t')
100             line++;
101           which = *line++;
102           if (which != 'c' && which != 'm')
103             abort();
104           while (*line == ' ' || *line == '\t')
105             line++;
106           if (!strncasecmp(line, "None", 4))
107             {
108               r = g = b = -1;
109               line += 4;
110             }
111           else
112             {
113               if (*line == '#')
114                 line++;
115               r = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
116               g = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
117               b = (hex[(int) line[0]] << 4) | hex[(int) line[1]]; line += 2;
118             }
119
120           if (which == 'c')
121             {
122               cmap[i].cr = r;
123               cmap[i].cg = g;
124               cmap[i].cb = b;
125             }
126           else
127             {
128               cmap[i].mr = r;
129               cmap[i].mg = g;
130               cmap[i].mb = b;
131             }
132         }
133
134       data++;
135     }
136
137   if (depth == 1) transparent_color = 1;
138
139   pixels = (unsigned long *) calloc (ncolors+1, sizeof(*pixels));
140   pixel_count = 0;
141   for (i = 0; i < ncolors; i++)
142     {
143       if (cmap[i].cr == -1) /* transparent */
144         {
145           rmap[(int) cmap[i].byte] = 255;
146         }
147       else
148         {
149           XColor color;
150           color.flags = DoRed|DoGreen|DoBlue;
151           color.red   = (cmap[i].cr << 8) | cmap[i].cr;
152           color.green = (cmap[i].cg << 8) | cmap[i].cg;
153           color.blue  = (cmap[i].cb << 8) | cmap[i].cb;
154           if (depth == 1 ||
155               !XAllocColor (dpy, colormap, &color))
156             {
157               color.red   = (cmap[i].mr << 8) | cmap[i].mr;
158               color.green = (cmap[i].mg << 8) | cmap[i].mg;
159               color.blue  = (cmap[i].mb << 8) | cmap[i].mb;
160               if (!XAllocColor (dpy, colormap, &color))
161                 abort();
162             }
163           pixels[pixel_count] = color.pixel;
164           rmap[(int) cmap[i].byte] = pixel_count;
165           pixel_count++;
166         }
167     }
168
169   ximage = XCreateImage (dpy, visual, depth,
170                          (depth == 1 ? XYBitmap : ZPixmap),
171                          0, 0, w, h, 8, 0);
172   if (ximage)
173     {
174       int x, y;
175       ximage->data = (char *) calloc (ximage->height, ximage->bytes_per_line);
176       for (y = 0; y < h; y++)
177         {
178           const char *line = *data++;
179           for (x = 0; x < w; x++)
180             {
181               int p = rmap[(int) *line];
182               line++;
183               XPutPixel (ximage, x, y,
184                          (p == 255 ? transparent_color : pixels[p]));
185
186               if (p == 255 && mask_ret)
187                 (*mask_ret)[(y * w8) + (x >> 3)] &= (~(1 << (x % 8)));
188             }
189         }
190     }
191   
192   *width_ret = w;
193   *height_ret = h;
194   *pixels_ret = pixels;
195   *npixels_ret = pixel_count;
196   return ximage;
197 }
198
199
200
201 /* Returns a pixmap of the xscreensaver logo.
202  */
203 Pixmap
204 xscreensaver_logo (Screen *screen, Visual *visual,
205                    Drawable drawable, Colormap cmap,
206                    unsigned long background_color,
207                    unsigned long **pixels_ret, int *npixels_ret,
208                    Pixmap *mask_ret,
209                    Bool big_p)
210 {
211   Display *dpy = DisplayOfScreen (screen);
212   int depth = visual_depth (screen, visual);
213   int iw, ih;
214   XImage *image;
215   Pixmap p = 0;
216   unsigned char *mask = 0;
217
218   image = parse_xpm_data (dpy, visual, cmap, depth, background_color,
219                           (big_p ? logo_180_xpm : logo_50_xpm),
220                           &iw, &ih, pixels_ret, npixels_ret,
221                           (mask_ret ? &mask : 0));
222
223   if (image)
224     {
225       XGCValues gcv;
226       GC gc;
227       p = XCreatePixmap (dpy, drawable, iw, ih, depth);
228       gc = XCreateGC (dpy, p, 0, &gcv);
229       XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih);
230       free (image->data);
231       image->data = 0;
232       XDestroyImage (image);
233       XFreeGC (dpy, gc);
234
235       if (mask_ret && mask)
236         {
237           *mask_ret = (Pixmap)
238             XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask,
239                                          iw, ih, 1L, 0L, 1);
240           free (mask);
241         }
242     }
243   return p;
244 }