858c68c90951ce82b6188502478331fba6648526
[xscreensaver] / utils / logo.c
1 /* xscreensaver, Copyright (c) 2001-2002 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                 unsigned 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 unsigned 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 unsigned char *line = *data++;
179           for (x = 0; x < w; x++)
180             {
181               int p = rmap[*line++];
182               XPutPixel (ximage, x, y,
183                          (p == 255 ? transparent_color : pixels[p]));
184
185               if (p == 255 && mask_ret)
186                 (*mask_ret)[(y * w8) + (x >> 3)] &= (~(1 << (x % 8)));
187             }
188         }
189     }
190   
191   *width_ret = w;
192   *height_ret = h;
193   *pixels_ret = pixels;
194   *npixels_ret = pixel_count;
195   return ximage;
196 }
197
198
199
200 /* Returns a pixmap of the xscreensaver logo.
201  */
202 Pixmap
203 xscreensaver_logo (Screen *screen, Visual *visual,
204                    Drawable drawable, Colormap cmap,
205                    unsigned long background_color,
206                    unsigned long **pixels_ret, int *npixels_ret,
207                    Pixmap *mask_ret,
208                    Bool big_p)
209 {
210   Display *dpy = DisplayOfScreen (screen);
211   int depth = visual_depth (screen, visual);
212   int iw, ih;
213   XImage *image;
214   Pixmap p = 0;
215   unsigned char *mask = 0;
216
217   image = parse_xpm_data (dpy, visual, cmap, depth, background_color,
218                           (big_p ? logo_180_xpm : logo_50_xpm),
219                           &iw, &ih, pixels_ret, npixels_ret,
220                           (mask_ret ? &mask : 0));
221
222   if (image)
223     {
224       XGCValues gcv;
225       GC gc;
226       p = XCreatePixmap (dpy, drawable, iw, ih, depth);
227       gc = XCreateGC (dpy, p, 0, &gcv);
228       XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih);
229       free (image->data);
230       image->data = 0;
231       XDestroyImage (image);
232       XFreeGC (dpy, gc);
233
234       if (mask_ret && mask)
235         {
236           *mask_ret = (Pixmap)
237             XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask,
238                                          iw, ih, 1L, 0L, 1);
239           free (mask);
240         }
241     }
242   return p;
243 }