http://ftp.x.org/contrib/applications/xscreensaver-2.23.tar.gz
[xscreensaver] / hacks / moire.c
1 /* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@netscape.com>
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  * Concept snarfed from Michael D. Bayne in
12  * http://www.go2net.com/internet/deep/1997/04/16/body.html
13  */
14
15 #include "screenhack.h"
16 #include <X11/Xutil.h>
17 #include <stdio.h>
18
19 int offset = 0;
20 XColor *colors = 0;
21 int ncolors = 0;
22 GC gc = 0;
23 unsigned long fg_pixel = 0;
24 unsigned long bg_pixel = 0;
25
26 static void
27 init_moire (Display *dpy, Window window)
28 {
29   int oncolors;
30   int i;
31   int fgh, bgh;
32   double fgs, fgv, bgs, bgv;
33   XWindowAttributes xgwa;
34   XColor fgc, bgc;
35   XGCValues gcv;
36   XGetWindowAttributes (dpy, window, &xgwa);
37
38   offset = get_integer_resource ("offset", "Integer");
39   if (offset < 2) offset = 2;
40
41  MONO:
42   if (colors)
43     {
44       for (i = 0; i < ncolors; i++)
45         XFreeColors (dpy, xgwa.colormap, &colors[i].pixel, 1, 0);
46       free(colors);
47       colors = 0;
48     }
49
50   if (mono_p)
51     {
52       fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(dpy));
53       bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(dpy));
54     }
55   else
56     {
57       fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy,
58                                      xgwa.colormap);
59       bg_pixel = get_pixel_resource ("background", "Background", dpy,
60                                      xgwa.colormap);
61     }
62
63   if (mono_p)
64     {
65       offset *= 20;   /* compensate for lack of shading */
66       gcv.foreground = fg_pixel;
67     }
68   else
69     {
70       ncolors = get_integer_resource ("ncolors", "Integer");
71       if (ncolors < 2) ncolors = 2;
72       oncolors = ncolors;
73
74       fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
75       if (get_boolean_resource("random","Boolean"))
76         {
77           fgc.red   = random() & 0xFFFF;
78           fgc.green = random() & 0xFFFF;
79           fgc.blue  = random() & 0xFFFF;
80           bgc.red   = random() & 0xFFFF;
81           bgc.green = random() & 0xFFFF;
82           bgc.blue  = random() & 0xFFFF;
83         }
84       else
85         {
86           fgc.pixel = fg_pixel;
87           bgc.pixel = bg_pixel;
88           XQueryColor (dpy, xgwa.colormap, &fgc);
89           XQueryColor (dpy, xgwa.colormap, &bgc);
90         }
91       rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
92       rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
93
94       colors = (XColor *) malloc (sizeof (XColor) * (ncolors+2));
95       memset(colors, 0, (sizeof (XColor) * (ncolors+2)));
96       make_color_ramp (dpy, xgwa.colormap,
97                        fgh, fgs, fgv, bgh, bgs, bgv,
98                        colors, &ncolors,
99                        True, True, False);
100       if (ncolors != oncolors)
101         fprintf(stderr, "%s: got %d of %d requested colors.\n",
102                 progname, ncolors, oncolors);
103
104       if (ncolors <= 2)
105         {
106           mono_p = True;
107           goto MONO;
108         }
109
110       gcv.foreground = colors[0].pixel;
111     }
112   gc = XCreateGC (dpy, window, GCForeground, &gcv);
113 }
114
115
116 static void
117 moire (Display *dpy, Window window, int offset, XColor *colors, int ncolors)
118 {
119   long x, y, xo, yo;
120   int factor = (random() % offset) + 1;
121   XGCValues gcv;
122   XWindowAttributes xgwa;
123   XImage *image;
124   int depth;
125   XGetWindowAttributes (dpy, window, &xgwa);
126
127   xo = (random() % xgwa.width)  - xgwa.width/2;
128   yo = (random() % xgwa.height) - xgwa.height/2;
129
130   depth = visual_depth(DefaultScreenOfDisplay(dpy), xgwa.visual);
131   image = XCreateImage (dpy, xgwa.visual,
132                         depth, ZPixmap, 0,       /* depth, format, offset */
133                         0, xgwa.width, 1, 8, 0); /* data, w, h, pad, bpl */
134
135   image->data = (char *) malloc (((xgwa.width + 1) * depth / 8)
136                                  * 2  /* uh, I dunno... */
137                                  );
138
139   for (y = 0; y < xgwa.height; y++)
140     {
141       for (x = 0; x < xgwa.width; x++)
142         {
143           double xx = x + xo;
144           double yy = y + yo;
145           double i = ((xx * xx) + (yy * yy)) / (double) factor;
146           if (mono_p)
147             gcv.foreground = ((((long) i) & 1) ? fg_pixel : bg_pixel);
148           else
149             gcv.foreground = colors[((long) i) % ncolors].pixel;
150           XPutPixel (image, x, 0, gcv.foreground);
151         }
152       XPutImage (dpy, window, gc, image, 0, 0, 0, y, xgwa.width, 1);
153       XSync(dpy, False);
154     }
155   if (image->data) free(image->data);
156   image->data = 0;
157   XDestroyImage (image);
158 }
159
160 \f
161 char *progclass = "Moire";
162
163 char *defaults [] = {
164   ".background:         blue",
165   ".foreground:         red",
166   "*random:             true",
167   "*delay:              5",
168   "*ncolors:            64",
169   "*offset:             50",
170   0
171 };
172
173 XrmOptionDescRec options [] = {
174   { "-random",          ".random",      XrmoptionSepArg, 0 },
175   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
176   { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
177   { "-offset",          ".offset",      XrmoptionSepArg, 0 },
178   { 0, 0, 0, 0 }
179 };
180
181 void
182 screenhack (Display *dpy, Window window)
183 {
184   int delay = get_integer_resource ("delay", "Integer");
185   while (1)
186     {
187       init_moire (dpy, window);
188       moire (dpy, window, offset, colors, ncolors);
189       XSync (dpy, True);
190       if (delay)
191         sleep(delay);
192     }
193 }