http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.04.2.tar.gz
[xscreensaver] / hacks / anemone.c
1 /* anemon, Copyright (c) 2001 Gabriel Finch
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 /*------------------------------------------------------------------------
13   |
14   |  FILE            anemone.c
15   |  MODULE OF       xscreensaver
16   |
17   |  DESCRIPTION     Anemone.
18   |
19   |  WRITTEN BY      Gabriel Finch
20   |                  
21   |
22   |
23   |  MODIFICATIONS   june 2001 started
24   |           
25   +----------------------------------------------------------------------*/
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include "screenhack.h"
34
35
36 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
37 #include "xdbe.h"
38 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
39
40
41 /*-----------------------------------------------------------------------+
42   |  PRIVATE DATA                                                          |
43   +-----------------------------------------------------------------------*/
44
45
46 #define TWO_PI     (2.0 * M_PI)
47 #define RND(x)     (random() % (x))
48 #define MAXPEND    2000
49 #define MAXPTS    200
50 #define TRUE 1
51 #define FALSE 0
52
53 static Display *dpy;
54 static Window window;
55
56 static Pixmap b,ba,bb;
57
58 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
59 static  XdbeBackBuffer backb;
60 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
61
62 static int
63 arms,                       /* number of arms */
64   finpoints;                  /* final number of points in each array. */
65 static long delay;              /* usecs to wait between updates. */
66
67 static int         scrWidth, scrHeight;
68 static GC          gcDraw, gcClear;
69
70 typedef struct {
71   double x,y,z;
72   int sx,sy,sz;
73 } vPend;
74
75 typedef unsigned short bool;
76
77 static bool dbuf;
78 static int width;
79
80 typedef struct {
81   long col;
82   int numpt;
83   int growth;
84   unsigned short rate;
85 } appDef;
86
87 static vPend *vPendage;  /* 3D representation of appendages */
88 static appDef *appD;  /* defaults */
89 static vPend *vCurr, *vNext;
90 static appDef *aCurr;
91
92 static double turn, turndelta;
93
94 static int    mx, my;            /* max screen coordinates. */
95 static int withdraw;
96
97 static    XGCValues         gcv;
98 static    Colormap          cmap;
99
100
101
102 /*-----------------------------------------------------------------------+
103   |  PUBLIC DATA                                                           |
104   +-----------------------------------------------------------------------*/
105
106 char *progclass = "Anemone";
107
108 char *defaults [] = {
109   ".background: black",
110   "*arms: 128",
111   "*width: 2",
112   "*finpoints: 64",
113   "*delay: 40000",
114   "*withdraw: 1200",
115   "*turnspeed: 50",
116 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
117   "*useDBE:             True",
118 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
119   0
120 };
121
122
123 XrmOptionDescRec options [] = {
124   { "-arms",        ".arms",        XrmoptionSepArg, 0 },
125   { "-finpoints",   ".finpoints",   XrmoptionSepArg, 0 },
126   { "-delay",       ".delay",       XrmoptionSepArg, 0 },
127   { "-width",       ".width",       XrmoptionSepArg, 0 },
128   { "-withdraw",    ".withdraw",    XrmoptionSepArg, 0 },
129   { "-turnspeed",   ".turnspeed",   XrmoptionSepArg, 0 },
130   { 0, 0, 0, 0 }
131 };
132 int options_size = (sizeof (options) / sizeof (options[0]));
133
134 /*-----------------------------------------------------------------------+
135   |  PRIVATE FUNCTIONS                                                     |
136   +-----------------------------------------------------------------------*/
137
138 static void *
139 xmalloc(size_t size)
140 {
141   void *ret;
142
143   if ((ret = malloc(size)) == NULL) {
144     fprintf(stderr, "anemone: out of memory\n");
145     exit(1);
146   }
147   return ret;
148 }
149
150
151 static void
152 initAppendages(void)
153 {
154   int    i;
155   /*int    marginx, marginy; */
156     
157   /*double scalex, scaley;*/
158
159   double x,y,z,dist;
160
161   mx = scrWidth - 1;
162   my = scrHeight - 1;
163
164   /* each appendage will have: colour,
165      number of points, and a grow or shrink indicator */
166
167   /* added: growth rate 1-10 (smaller==faster growth) */
168   /* each appendage needs virtual coords (x,y,z) with y and z combining to
169      give the screen y */
170
171   vPendage = (vPend *) xmalloc((finpoints + 1) * sizeof(vPend) * arms);
172   appD = (appDef *) xmalloc(sizeof(appDef) * arms);
173
174
175   for (i = 0; i < arms; i++) {
176     aCurr = appD + i;
177     vCurr = vPendage + (finpoints + 1) * i;
178     vNext = vCurr + 1;
179
180     aCurr->col = (long)RND(256)*RND(256)+32768;
181     aCurr->numpt = 1;
182     aCurr->growth=finpoints/2+RND(finpoints/2);
183     aCurr->rate=RND(11)*RND(11);
184
185     dist=1.;
186
187     do {
188       x=(1-RND(1001)/500);
189       y=(1-RND(1001)/500);
190       z=(1-RND(1001)/500);
191       dist=x*x+y*y+z*z;
192     } while (dist>=1.);
193
194     vCurr->x=x*200;
195     vCurr->y=my/2+y*200;
196     vCurr->z=0+z*200;
197
198     /* start the arm going outwards */
199     vCurr->sx=vCurr->x/5;
200     vCurr->sy=(vCurr->y-my/2)/5;
201     vCurr->sz=(vCurr->z)/5;
202
203     
204     vNext->x=vCurr->x+vCurr->sx;
205     vNext->y=vCurr->y+vCurr->sy;
206     vNext->z=vCurr->z+vCurr->sz;
207   }
208 }
209
210 static void
211 initAnemone(void)
212 {
213   XWindowAttributes wa;
214
215   turn = 0.;
216   
217   width = get_integer_resource("width", "Integer");
218   arms = get_integer_resource("arms", "Integer");
219   finpoints = get_integer_resource("finpoints", "Integer");
220   delay = get_integer_resource("delay", "Integer");
221   withdraw = get_integer_resource("withdraw", "Integer");
222   turndelta = get_float_resource("turnspeed", "float")/100000;
223
224   dbuf=TRUE;
225
226
227   b=ba=bb=0;    /* double-buffer to reduce flicker */
228 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
229   b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
230 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
231
232
233   XGetWindowAttributes(dpy, window, &wa);
234   scrWidth = wa.width;
235   scrHeight = wa.height;
236   cmap = wa.colormap;
237   gcDraw = XCreateGC(dpy, window, GCForeground, &gcv);
238   gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap);
239   gcClear = XCreateGC(dpy, window, GCForeground, &gcv);
240
241   if (dbuf) {
242     if (!b)
243       {
244         ba = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth);
245         bb = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth);
246         b = ba;
247       }
248   }
249   else
250     {   
251       b = window;
252     }
253
254   if (ba) XFillRectangle (dpy, ba, gcClear, 0, 0, scrWidth, scrHeight);
255   if (bb) XFillRectangle (dpy, bb, gcClear, 0, 0, scrWidth, scrHeight);
256
257   XClearWindow(dpy, window);
258   XSetLineAttributes(dpy, gcDraw,  width, LineSolid, CapRound, JoinBevel);
259
260   initAppendages();
261 }
262
263
264 static void
265 createPoints(void)
266 {
267   int i;
268   int withdrawall=RND(withdraw);
269
270   for (i = 0; i< arms; i++) {
271     aCurr = appD + i;
272     if (!withdrawall) {
273       aCurr->growth=-finpoints;
274       turndelta=-turndelta;
275     }
276
277     else if (withdrawall<11) aCurr->growth=-aCurr->numpt;
278
279     else if (RND(100)<aCurr->rate) {
280       if (aCurr->growth>0) {
281         if (!(--aCurr->growth)) aCurr->growth=-RND(finpoints)-1;
282         vCurr = vPendage + (finpoints + 1) * i + aCurr->numpt-1;
283         if (aCurr->numpt<finpoints - 1) {
284           /* add a piece */     
285           vNext=vCurr + 1;
286           aCurr->numpt++;
287           vNext->sx=vCurr->sx+RND(3)-1;
288           vNext->sy=vCurr->sy+RND(3)-1;
289           vNext->sz=vCurr->sz+RND(3)-1;
290           vCurr=vNext+1;
291           vCurr->x=vNext->x+vNext->sx;
292           vCurr->y=vNext->y+vNext->sy;
293           vCurr->z=vNext->z+vNext->sz;
294         }
295       }
296     }
297   }
298 }
299
300
301 static void
302 drawImage(Drawable curr_window, double sint, double cost)
303 {
304   int q,numpt,mx2=mx/2;
305   double cx,cy,cz,nx,ny,nz;
306
307   if ((numpt=aCurr->numpt)==1) return;
308   XSetForeground(dpy, gcDraw, aCurr->col);
309     
310   vNext=vCurr+1;
311
312   cx=vCurr->x;
313   cy=vCurr->y;
314   cz=vCurr->z;
315
316
317   for (q = 0; q < numpt-1; q++) {
318     nx=vNext->x+2-RND(5);
319     ny=vNext->y+2-RND(5);
320     nz=vNext->z+2-RND(5);
321
322     XDrawLine(dpy, curr_window, gcDraw,mx2+cx*cost-cz*sint, cy, mx2+nx*cost-nz*sint, ny);
323     vCurr++;
324     vNext++;
325
326     cx=nx;
327     cy=ny;
328     cz=nz;
329   }
330   XSetLineAttributes(dpy, gcDraw, width*3, LineSolid, CapRound, JoinBevel);
331   XDrawLine(dpy, curr_window, gcDraw,mx/2+cx*cost-cz*sint, cy, mx/2+nx*cost-nz*sint, ny);
332   XSetLineAttributes(dpy, gcDraw, width, LineSolid, CapRound, JoinBevel);
333
334 }
335
336 static void
337 animateAnemone(Drawable curr_window)
338 {
339   int i;
340   double sint=sin(turn),cost=cos(turn);
341
342   aCurr = appD;
343   for (i = 0; i< arms; i++) {
344     vCurr=vPendage + (finpoints + 1) * i;
345     if (RND(25)<aCurr->rate) {
346       if (aCurr->growth<0) {
347         aCurr->numpt-=aCurr->numpt>1;
348         if (!(++aCurr->growth)) aCurr->growth=RND(finpoints-aCurr->numpt)+1;
349       }
350     }
351     drawImage(curr_window, sint, cost);
352     turn+=turndelta;
353     aCurr++;
354   }
355   createPoints();
356   usleep(delay);
357
358   if (turn>=TWO_PI) turn-=TWO_PI;
359 }
360
361 /*-----------------------------------------------------------------------+
362   |  PUBLIC FUNCTIONS                                                      |
363   +-----------------------------------------------------------------------*/
364
365 void
366 screenhack(Display *disp, Window win)
367 {
368
369   dpy=disp;
370   window=win;
371
372   initAnemone();
373   for (;;) {
374
375     XFillRectangle (dpy, b, gcClear, 0, 0, scrWidth, scrHeight);
376
377     animateAnemone(b);
378
379 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
380     if (backb)
381       {
382         XdbeSwapInfo info[1];
383         info[0].swap_window = window;
384         info[0].swap_action = XdbeUndefined;
385         XdbeSwapBuffers (dpy, info, 1);
386       }
387     else
388 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
389       if (dbuf)
390         {
391           XCopyArea (dpy, b, window, gcClear, 0, 0,
392                      scrWidth, scrHeight, 0, 0);
393           b = (b == ba ? bb : ba);
394         }
395
396     screenhack_handle_events (dpy);
397   }
398
399 }
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414