ftp://ftp.smr.ru/pub/0/FreeBSD/releases/distfiles/xscreensaver-3.16.tar.gz
[xscreensaver] / hacks / moire.c
1 /* xscreensaver, Copyright (c) 1997, 1998 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  * 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 #ifdef HAVE_XSHM_EXTENSION
20 # include "xshm.h"
21 static Bool use_shm;
22 static XShmSegmentInfo shm_info;
23 #endif /* HAVE_XSHM_EXTENSION */
24
25 static int offset = 0;
26 static XColor *colors = 0;
27 static int ncolors = 0;
28 static GC gc = 0;
29 static unsigned long fg_pixel = 0;
30 static unsigned long bg_pixel = 0;
31
32 static void
33 init_moire (Display *dpy, Window window)
34 {
35   int oncolors;
36   int i;
37   int fgh, bgh;
38   double fgs, fgv, bgs, bgv;
39   XWindowAttributes xgwa;
40   XColor fgc, bgc;
41   XGCValues gcv;
42   XGetWindowAttributes (dpy, window, &xgwa);
43
44   offset = get_integer_resource ("offset", "Integer");
45   if (offset < 2) offset = 2;
46
47 #ifdef HAVE_XSHM_EXTENSION
48   use_shm = get_boolean_resource("useSHM", "Boolean");
49 #endif /*  HAVE_XSHM_EXTENSION */
50
51  MONO:
52   if (colors)
53     {
54       for (i = 0; i < ncolors; i++)
55         XFreeColors (dpy, xgwa.colormap, &colors[i].pixel, 1, 0);
56       free(colors);
57       colors = 0;
58     }
59
60   if (mono_p)
61     {
62       fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(dpy));
63       bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(dpy));
64     }
65   else
66     {
67       fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy,
68                                      xgwa.colormap);
69       bg_pixel = get_pixel_resource ("background", "Background", dpy,
70                                      xgwa.colormap);
71     }
72
73   if (mono_p)
74     {
75       offset *= 20;   /* compensate for lack of shading */
76       gcv.foreground = fg_pixel;
77     }
78   else
79     {
80       ncolors = get_integer_resource ("ncolors", "Integer");
81       if (ncolors < 2) ncolors = 2;
82       oncolors = ncolors;
83
84       fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
85       if (get_boolean_resource("random","Boolean"))
86         {
87           fgc.red   = random() & 0xFFFF;
88           fgc.green = random() & 0xFFFF;
89           fgc.blue  = random() & 0xFFFF;
90           bgc.red   = random() & 0xFFFF;
91           bgc.green = random() & 0xFFFF;
92           bgc.blue  = random() & 0xFFFF;
93         }
94       else
95         {
96           fgc.pixel = fg_pixel;
97           bgc.pixel = bg_pixel;
98           XQueryColor (dpy, xgwa.colormap, &fgc);
99           XQueryColor (dpy, xgwa.colormap, &bgc);
100         }
101       rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
102       rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
103
104       colors = (XColor *) malloc (sizeof (XColor) * (ncolors+2));
105       memset(colors, 0, (sizeof (XColor) * (ncolors+2)));
106       make_color_ramp (dpy, xgwa.colormap,
107                        fgh, fgs, fgv, bgh, bgs, bgv,
108                        colors, &ncolors,
109                        True, True, False);
110       if (ncolors != oncolors)
111         fprintf(stderr, "%s: got %d of %d requested colors.\n",
112                 progname, ncolors, oncolors);
113
114       if (ncolors <= 2)
115         {
116           mono_p = True;
117           goto MONO;
118         }
119
120       gcv.foreground = colors[0].pixel;
121     }
122   gc = XCreateGC (dpy, window, GCForeground, &gcv);
123 }
124
125
126 static void
127 moire (Display *dpy, Window window, int offset, XColor *colors, int ncolors)
128 {
129   long x, y, xo, yo;
130   int factor = (random() % offset) + 1;
131   XGCValues gcv;
132   XWindowAttributes xgwa;
133   XImage *image;
134   int depth;
135   XGetWindowAttributes (dpy, window, &xgwa);
136
137   xo = (random() % xgwa.width)  - xgwa.width/2;
138   yo = (random() % xgwa.height) - xgwa.height/2;
139
140   depth = visual_depth(DefaultScreenOfDisplay(dpy), xgwa.visual);
141
142   image = 0;
143 # ifdef HAVE_XSHM_EXTENSION
144   if (use_shm)
145     {
146       image = create_xshm_image(dpy, xgwa.visual, depth, ZPixmap, 0,
147                                 &shm_info, xgwa.width, 1);
148       if (!image)
149         use_shm = False;
150     }
151 # endif /* HAVE_XSHM_EXTENSION */
152
153   if (!image)
154     {
155       image = XCreateImage (dpy, xgwa.visual,
156                             depth, ZPixmap, 0,      /* depth, format, offset */
157                             0, xgwa.width, 1, 8, 0); /* data, w, h, pad, bpl */
158       image->data = (char *) calloc(image->height, image->bytes_per_line);
159     }
160
161   for (y = 0; y < xgwa.height; y++)
162     {
163       for (x = 0; x < xgwa.width; x++)
164         {
165           double xx = x + xo;
166           double yy = y + yo;
167           double i = ((xx * xx) + (yy * yy)) / (double) factor;
168           if (mono_p)
169             gcv.foreground = ((((long) i) & 1) ? fg_pixel : bg_pixel);
170           else
171             gcv.foreground = colors[((long) i) % ncolors].pixel;
172           XPutPixel (image, x, 0, gcv.foreground);
173         }
174
175 # ifdef HAVE_XSHM_EXTENSION
176       if (use_shm)
177         XShmPutImage(dpy, window, gc, image, 0, 0, 0, y, xgwa.width, 1, False);
178       else
179 # endif /*  HAVE_XSHM_EXTENSION */
180         XPutImage (dpy, window, gc, image, 0, 0, 0, y, xgwa.width, 1);
181
182       XSync(dpy, False);
183     }
184
185 # ifdef HAVE_XSHM_EXTENSION
186   if (!use_shm)
187 # endif /*  HAVE_XSHM_EXTENSION */
188     if (image->data)
189       {
190         free(image->data);
191         image->data = 0;
192       }
193
194   XDestroyImage (image);
195 }
196
197 \f
198 char *progclass = "Moire";
199
200 char *defaults [] = {
201   ".background:         blue",
202   ".foreground:         red",
203   "*random:             true",
204   "*delay:              5",
205   "*ncolors:            64",
206   "*offset:             50",
207 #ifdef HAVE_XSHM_EXTENSION
208   "*useSHM:           True",
209 #endif /*  HAVE_XSHM_EXTENSION */
210   0
211 };
212
213 XrmOptionDescRec options [] = {
214   { "-random",          ".random",      XrmoptionSepArg, 0 },
215   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
216   { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
217   { "-offset",          ".offset",      XrmoptionSepArg, 0 },
218 #ifdef HAVE_XSHM_EXTENSION
219   { "-shm",             ".useSHM",      XrmoptionNoArg, "True" },
220   { "-no-shm",          ".useSHM",      XrmoptionNoArg, "False" },
221 #endif /*  HAVE_XSHM_EXTENSION */
222   { 0, 0, 0, 0 }
223 };
224
225 void
226 screenhack (Display *dpy, Window window)
227 {
228   int delay = get_integer_resource ("delay", "Integer");
229   while (1)
230     {
231       init_moire (dpy, window);
232       moire (dpy, window, offset, colors, ncolors);
233       XSync (dpy, False);
234       screenhack_handle_events (dpy);
235       if (delay)
236         sleep(delay);
237     }
238 }