1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* anemone ---  */
3 
4 #if 0
5 static const char sccsid[] = "@(#)anemone.c	5.22 2006/03/04 xlockmore";
6 
7 #endif
8 
9 /* anemon, Copyright (c) 2001 Gabriel Finch
10  *
11  * Permission to use, copy, modify, distribute, and sell this software and its
12  * documentation for any purpose is hereby granted without fee, provided that
13  * the above copyright notice appear in all copies and that both that
14  * copyright notice and this permission notice appear in supporting
15  * documentation.  No representations are made about the suitability of this
16  * software for any purpose.  It is provided "as is" without express or
17  * implied warranty.
18  */
19 
20 /*------------------------------------------------------------------------
21   |
22   |  FILE            anemone.c
23   |  MODULE OF       xscreensaver
24   |
25   |  DESCRIPTION     Anemone.
26   |
27   |  WRITTEN BY      Gabriel Finch
28   |
29   |
30   |
31   |  MODIFICATIONS   june 2001 started
32   |                  March 2006 adaption for xlockmore
33   |
34   +----------------------------------------------------------------------*/
35 
36 
37 
38 #ifdef STANDALONE
39 # define MODE_anemone
40 # define DEFAULTS	"*delay: 100000 \n" \
41 			"*size: 4 \n" \
42 			"*ncolors: 8 \n" \
43 			"*fullrandom: True \n" \
44 			"*verbose: False \n" \
45 			"*delay: 40000 \n" \
46 
47 #if 0
48 	".background: black \n" \
49 
50 #endif
51 #if 0
52 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
53 	"*useDBE: True \n" \
54 
55 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
56 #endif
57 # define reshape_anemone 0
58 # define anemone_handle_event 0
59 # include "xlockmore.h"		/* in xscreensaver distribution */
60 #else /* STANDALONE */
61 # include "xlock.h"		/* in xlockmore distribution */
62 #endif /* STANDALONE */
63 
64 #ifdef MODE_anemone
65 
66 #undef HAVE_DOUBLE_BUFFER_EXTENSION
67 /* xdbe_get_backbuffer does not exist */
68 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
69 #include "xdbe.h"
70 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
71 
72 
73 /*-----------------------------------------------------------------------+
74   |  PRIVATE DATA                                                          |
75   +-----------------------------------------------------------------------*/
76 
77 
78 #define TWO_PI     (2.0 * M_PI)
79 #define MAXPEND    2000
80 #define MAXPTS    200
81 
82 #define DEF_ARMS "256"
83 #define DEF_FINPOINTS "64"
84 #define DEF_WIDTH "2"
85 #define DEF_WITHDRAW "2400"
86 #define DEF_TURNSPEED "5"
87 
88 static int st_arms;
89 static int st_finpoints;
90 static int st_width;
91 static int st_withdraw;
92 static int st_turnspeed;
93 
94 typedef struct {
95   double x,y,z;
96   int sx,sy,sz;
97 } vPend;
98 
99 typedef struct {
100   long col;
101   int numpt;
102   int growth;
103   unsigned short rate;
104 } appDef;
105 
106 
107 typedef struct {
108   Display *dpy;
109   Window window;
110 
111   Pixmap b,ba,bb;
112 
113 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
114   XdbeBackBuffer backb;
115 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
116 
117   int
118     arms,                       /* number of arms */
119     finpoints;                  /* final number of points in each array. */
120 
121   int         scrWidth, scrHeight;
122   GC          gcDraw, gcClear;
123 
124 
125   unsigned short dbuf;
126   int width;
127 
128   vPend *vPendage;  /* 3D representation of appendages */
129   appDef *appD;  /* defaults */
130   vPend *vCurr, *vNext;
131   appDef *aCurr;
132 
133   double turn, turndelta;
134 
135   int    mx, my;            /* max screen coordinates. */
136   int withdraw;
137 
138   XGCValues         gcv;
139   Colormap          cmap;
140 } anemonestruct;
141 
142 static anemonestruct *anemones = (anemonestruct *) NULL;
143 
144 
145 /*-----------------------------------------------------------------------+
146   |  PUBLIC DATA                                                           |
147   +-----------------------------------------------------------------------*/
148 
149 static XrmOptionDescRec opts[] =
150 {
151    {(char *) "-arms", (char *) ".anemone.arms", XrmoptionSepArg, (caddr_t) NULL},
152    {(char *) "-finpoints", (char *) ".anemone.finpoints", XrmoptionSepArg, (caddr_t) NULL},
153    {(char *) "-width", (char *) ".anemone.width", XrmoptionSepArg, (caddr_t) NULL},
154    {(char *) "-withdraw", (char *) ".anemone.withdraw", XrmoptionSepArg, (caddr_t) NULL},
155    {(char *) "-turnspeed", (char *) ".anemone.turnspeed", XrmoptionSepArg, (caddr_t) NULL}
156 };
157 
158 static argtype vars[] =
159 {
160    {(void *) &st_arms, (char *) "arms",
161    (char *) "Arms", (char *) DEF_ARMS , t_Int},
162    {(void *) &st_finpoints, (char *) "finpoints",
163    (char *) "Finpoints", (char *) DEF_FINPOINTS , t_Int},
164    {(void *) &st_width, (char *) "width",
165    (char *) "Width", (char *) DEF_WIDTH , t_Int},
166    {(void *) &st_withdraw, (char *) "withdraw",
167    (char *) "Withdt=raw", (char *) DEF_WITHDRAW , t_Int},
168    {(void *) &st_turnspeed, (char *) "turnspeed",
169    (char *) "Turnspeed", (char *) DEF_TURNSPEED , t_Int}
170 };
171 
172 
173 static OptionStruct desc[] =
174 {
175    {(char *) "-arms num", (char *) "Number of arms"},
176    {(char *) "-width num", (char *) "Width of arms"},
177    {(char *) "-finpoints num", (char *) "final number of points in each array"},
178    {(char *) "-withdraw num", (char *) "withdraw frequency"},
179    {(char *) "-turnspeed num", (char *) "turning speed"}
180 };
181 
182 ENTRYPOINT ModeSpecOpt anemone_opts =
183 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
184 
185 #ifdef USE_MODULES
186 ModStruct   anemone_description =
187 {"anemone", "init_anemone", "draw_anemone", "release_anemone",
188  (char *) NULL, "init_anemone", "free_anemone", &anemone_opts,
189  50000, 1, 1, 1, 64, 1.0, "",
190  "Shows wiggling tentacles", 0, NULL};
191 
192 #endif
193 
194 /*-----------------------------------------------------------------------+
195   |  PRIVATE FUNCTIONS                                                     |
196   +-----------------------------------------------------------------------*/
197 
198 static void
free_anemone_screen(Display * display,anemonestruct * sp)199 free_anemone_screen(Display *display, anemonestruct *sp)
200 {
201    if (sp == NULL) {
202         return;
203    }
204    if ( sp->vPendage )
205      {
206 	free( sp->vPendage );
207 	sp->vPendage = (vPend*) NULL;
208      }
209    if ( sp->appD )
210      {
211 	free( sp->appD );
212 	sp->appD = (appDef*) NULL;
213      }
214    if ( sp->gcDraw != None )
215      {
216 	XFreeGC(display, sp->gcDraw );
217 	sp->gcDraw = None;
218      }
219    if ( sp->gcClear != None )
220      {
221 	XFreeGC(display, sp->gcClear );
222 	sp->gcClear = None;
223      }
224    if (sp->ba != None)
225      {
226 	XFreePixmap(display, sp->ba);
227 	sp->ba = None;
228      }
229    if (sp->bb != None)
230      {
231 	XFreePixmap(display, sp->bb);
232 	sp->bb = None;
233      }
234    sp = NULL;
235 }
236 
237 ENTRYPOINT void
free_anemone(ModeInfo * mi)238 free_anemone(ModeInfo * mi)
239 {
240   free_anemone_screen(MI_DISPLAY(mi), &anemones[MI_SCREEN(mi)]);
241 }
242 
243 static void *
xmalloc(size_t size)244 xmalloc(size_t size)
245 {
246   void *ret;
247 
248   if ((ret = malloc(size)) == NULL) {
249     fprintf(stderr, "anemone: out of memory\n");
250   }
251   return ret;
252 }
253 
254 
255 static void
initAppendages(ModeInfo * mi,anemonestruct * sp)256 initAppendages(ModeInfo *mi, anemonestruct *sp)
257 {
258   int    i;
259   /*int    marginx, marginy; */
260 
261   /*double scalex, scaley;*/
262 
263   double x,y,z,dist;
264 
265   sp->mx = sp->scrWidth - 1;
266   sp->my = sp->scrHeight - 1;
267 
268   /* each appendage will have: colour,
269      number of points, and a grow or shrink indicator */
270 
271   /* added: growth rate 1-10 (smaller==faster growth) */
272   /* each appendage needs virtual coords (x,y,z) with y and z combining to
273      give the screen y */
274 
275   sp->vPendage = (vPend *) xmalloc((sp->finpoints + 1) * sizeof(vPend) * sp->arms);
276   sp->appD = (appDef *) xmalloc(sizeof(appDef) * sp->arms);
277 
278 
279   for (i = 0; i < sp->arms; i++) {
280     sp->aCurr = sp->appD + i;
281     sp->vCurr = sp->vPendage + (sp->finpoints + 1) * i;
282     sp->vNext = sp->vCurr + 1;
283 
284 #ifdef WIN32
285     sp->aCurr->col = (long)NRAND(MI_NCOLORS(mi));
286 #else
287     sp->aCurr->col = (long)NRAND(256)*NRAND(256)+32768;
288 #endif
289     sp->aCurr->numpt = 1;
290     sp->aCurr->growth=sp->finpoints/2+NRAND(sp->finpoints/2);
291     sp->aCurr->rate=NRAND(11)*NRAND(11);
292 
293     dist=1.;
294 
295     do {
296       x=(1-NRAND(1001)/500);
297       y=(1-NRAND(1001)/500);
298       z=(1-NRAND(1001)/500);
299       dist=x*x+y*y+z*z;
300     } while (dist>=1.);
301 
302     sp->vCurr->x=x*200;
303     sp->vCurr->y=sp->my/2+y*200;
304     sp->vCurr->z=0+z*200;
305 
306     /* start the arm going outwards */
307     sp->vCurr->sx=(int) (sp->vCurr->x/5);
308     sp->vCurr->sy=(int) ((sp->vCurr->y-sp->my/2)/5);
309     sp->vCurr->sz=(int) (sp->vCurr->z/5);
310 
311 
312     sp->vNext->x=sp->vCurr->x+sp->vCurr->sx;
313     sp->vNext->y=sp->vCurr->y+sp->vCurr->sy;
314     sp->vNext->z=sp->vCurr->z+sp->vCurr->sz;
315   }
316 }
317 
318 static void
initAnemone(ModeInfo * mi,anemonestruct * sp)319 initAnemone( ModeInfo * mi , anemonestruct *sp )
320 {
321   XWindowAttributes wa;
322 
323   sp->turn = 0.;
324    if ( st_width < 0 )
325      sp->width = NRAND( -st_width ) + 1;
326    else
327      sp->width = st_width;
328    if ( st_arms < 0 )
329      sp->arms = NRAND( -st_arms ) + 1;
330    else
331      sp->arms = st_arms;
332    if ( st_finpoints < 0 )
333      sp->finpoints = NRAND( -st_finpoints ) + 1;
334    else
335      sp->finpoints = st_finpoints;
336    if ( st_withdraw < 0 )
337      sp->withdraw = NRAND( -st_withdraw );
338    else
339      sp->withdraw = st_withdraw;
340    if ( st_turnspeed < 0 )
341      sp->turndelta = NRAND( -st_turnspeed ) / 10000.;
342    else
343      sp->turndelta =st_turnspeed / 10000.0;
344 
345 #ifdef WIN32
346   sp->dbuf=False;
347 #else
348   sp->dbuf=True;
349 #endif
350 
351   sp->b=sp->ba=sp->bb=0;	/* double-buffer to reduce flicker */
352 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
353   sp->b = sp->backb = xdbe_get_backbuffer (sp->dpy, sp->window, XdbeUndefined);
354 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
355 
356 
357   XGetWindowAttributes(sp->dpy, sp->window, &wa);
358   sp->scrWidth = wa.width;
359   sp->scrHeight = wa.height;
360   sp->cmap = wa.colormap;
361   sp->gcDraw = XCreateGC(sp->dpy, sp->window, GCForeground, &sp->gcv);
362   sp->gcv.foreground = MI_BLACK_PIXEL(mi);
363   sp->gcClear = XCreateGC(sp->dpy, sp->window, GCForeground, &sp->gcv);
364 
365   if (sp->dbuf) {
366     if (!sp->b)
367       {
368 	sp->ba = XCreatePixmap (sp->dpy, sp->window, sp->scrWidth, sp->scrHeight, wa.depth);
369 	sp->bb = XCreatePixmap (sp->dpy, sp->window, sp->scrWidth, sp->scrHeight, wa.depth);
370 	sp->b = sp->ba;
371       }
372   }
373   else
374     {
375      sp->b= sp->window;
376     }
377 
378   if (sp->ba) XFillRectangle (sp->dpy, sp->ba, sp->gcClear, 0, 0, sp->scrWidth, sp->scrHeight);
379   if (sp->bb) XFillRectangle (sp->dpy, sp->bb, sp->gcClear, 0, 0, sp->scrWidth, sp->scrHeight);
380 
381   XClearWindow(sp->dpy, sp->window);
382   XSetLineAttributes(sp->dpy, sp->gcDraw,  sp->width, LineSolid, CapRound, JoinBevel);
383 
384   initAppendages(mi, sp);
385 }
386 
387 
388 static void
createPoints(anemonestruct * sp)389 createPoints(anemonestruct *sp)
390 {
391   int i;
392   int withdrawall=NRAND(sp->withdraw);
393 
394   for (i = 0; i< sp->arms; i++) {
395     sp->aCurr = sp->appD + i;
396     if (!withdrawall) {
397       sp->aCurr->growth=-sp->finpoints;
398       sp->turndelta=-sp->turndelta;
399     }
400 
401     else if (withdrawall<11) sp->aCurr->growth=-sp->aCurr->numpt;
402 
403     else if (NRAND(100)<sp->aCurr->rate) {
404       if (sp->aCurr->growth>0) {
405 	if (!(--sp->aCurr->growth)) sp->aCurr->growth=-NRAND(sp->finpoints)-1;
406 	sp->vCurr = sp->vPendage + (sp->finpoints + 1) * i + sp->aCurr->numpt-1;
407 	if (sp->aCurr->numpt<sp->finpoints - 1) {
408 	  /* add a piece */
409 	  sp->vNext=sp->vCurr + 1;
410 	  sp->aCurr->numpt++;
411 	  sp->vNext->sx=sp->vCurr->sx+NRAND(3)-1;
412 	  sp->vNext->sy=sp->vCurr->sy+NRAND(3)-1;
413 	  sp->vNext->sz=sp->vCurr->sz+NRAND(3)-1;
414 	  sp->vCurr=sp->vNext+1;
415 	  sp->vCurr->x=sp->vNext->x+sp->vNext->sx;
416 	  sp->vCurr->y=sp->vNext->y+sp->vNext->sy;
417 	  sp->vCurr->z=sp->vNext->z+sp->vNext->sz;
418 	}
419       }
420     }
421   }
422 }
423 
424 
425 static void
drawImage(Drawable curr_window,double sint,double cost,anemonestruct * sp,ModeInfo * mi)426 drawImage(Drawable curr_window, double sint, double cost , anemonestruct *sp, ModeInfo *mi)
427 {
428   int q,numpt,mx2=sp->mx/2;
429   double cx,cy,cz,nx=0,ny=0,nz=0;
430 
431   if ((numpt=sp->aCurr->numpt)==1) return;
432 #ifdef WIN32
433   XSetForeground(sp->dpy, sp->gcDraw, MI_PIXEL(mi, sp->aCurr->col));
434 #else
435   XSetForeground(sp->dpy, sp->gcDraw, sp->aCurr->col);
436 #endif
437 
438   sp->vNext=sp->vCurr+1;
439 
440   cx=sp->vCurr->x;
441   cy=sp->vCurr->y;
442   cz=sp->vCurr->z;
443 
444 
445   for (q = 0; q < numpt-1; q++) {
446     nx=sp->vNext->x+2-NRAND(5);
447     ny=sp->vNext->y+2-NRAND(5);
448     nz=sp->vNext->z+2-NRAND(5);
449 
450     XDrawLine(sp->dpy, curr_window, sp->gcDraw,
451 	(int) (mx2+cx*cost-cz*sint), (int) cy,
452 	(int) (mx2+nx*cost-nz*sint), (int) ny);
453     sp->vCurr++;
454     sp->vNext++;
455 
456     cx=nx;
457     cy=ny;
458     cz=nz;
459   }
460   XSetLineAttributes(sp->dpy, sp->gcDraw, sp->width*3, LineSolid, CapRound, JoinBevel);
461   XDrawLine(sp->dpy, curr_window, sp->gcDraw,
462 	(int) (sp->mx/2+cx*cost-cz*sint), (int) cy,
463 	(int) (sp->mx/2+nx*cost-nz*sint), (int) ny);
464   XSetLineAttributes(sp->dpy, sp->gcDraw, sp->width, LineSolid, CapRound, JoinBevel);
465 
466 }
467 
468 static void
animateAnemone(Drawable curr_window,anemonestruct * sp,ModeInfo * mi)469 animateAnemone(Drawable curr_window , anemonestruct *sp, ModeInfo *mi)
470 {
471   int i;
472   double sint=sin(sp->turn),cost=cos(sp->turn);
473 
474   sp->aCurr = sp->appD;
475   for (i = 0; i< sp->arms; i++) {
476     sp->vCurr=sp->vPendage + (sp->finpoints + 1) * i;
477     if (NRAND(25)<sp->aCurr->rate) {
478       if (sp->aCurr->growth<0) {
479 	sp->aCurr->numpt-=sp->aCurr->numpt>1;
480 	if (!(++sp->aCurr->growth)) sp->aCurr->growth=NRAND(sp->finpoints-sp->aCurr->numpt)+1;
481       }
482     }
483     drawImage(curr_window, sint, cost , sp, mi);
484     sp->turn+=sp->turndelta;
485     sp->aCurr++;
486   }
487   createPoints(sp);
488 
489   if (sp->turn>=TWO_PI) sp->turn-=TWO_PI;
490 }
491 
492 /*-----------------------------------------------------------------------+
493   |  PUBLIC FUNCTIONS                                                      |
494   +-----------------------------------------------------------------------*/
495 
496 ENTRYPOINT void
init_anemone(ModeInfo * mi)497 init_anemone(ModeInfo * mi)
498 {
499    anemonestruct *sp;
500 
501    MI_INIT(mi, anemones);
502    sp = &anemones[MI_SCREEN(mi)];
503 
504    sp->dpy= MI_DISPLAY(mi);
505    sp->window=MI_WINDOW(mi);
506 
507    initAnemone( mi , sp );
508 
509    XFillRectangle (sp->dpy, sp->b, sp->gcClear, 0, 0, sp->scrWidth, sp->scrHeight);
510 
511    animateAnemone( sp->b , sp, mi);
512 }
513 
514 ENTRYPOINT void
draw_anemone(ModeInfo * mi)515 draw_anemone(ModeInfo * mi)
516 {
517    anemonestruct *sp = &anemones[MI_SCREEN(mi)];
518 
519    if (anemones == NULL)
520 	return;
521    MI_IS_DRAWN(mi) = True;
522 
523 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
524     if (sp->backb)
525       {
526 	XdbeSwapInfo info[1];
527 	info[0].swap_window = sp->window;
528 	info[0].swap_action = XdbeUndefined;
529 	XdbeSwapBuffers (sp->dpy, info, 1);
530       }
531     else
532 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
533       if (sp->dbuf)
534 	{
535 	  XCopyArea (sp->dpy, sp->b, sp->window, sp->gcClear, 0, 0,
536 		     sp->scrWidth, sp->scrHeight, 0, 0);
537 	 sp->b = (sp->b == sp->ba ? sp->bb : sp->ba);
538 	}
539 
540    XFillRectangle (sp->dpy, sp->b, sp->gcClear, 0, 0, sp->scrWidth, sp->scrHeight);
541 
542     animateAnemone( sp->b , sp, mi);
543 }
544 
545 ENTRYPOINT void
release_anemone(ModeInfo * mi)546 release_anemone(ModeInfo * mi)
547 {
548    if (anemones != NULL) {
549       int screen;
550 
551       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
552 	free_anemone_screen(MI_DISPLAY(mi), &anemones[screen]);
553       free(anemones);
554       anemones = (anemonestruct *) NULL;
555    }
556 }
557 
558 /*
559 void
560 refresh_anemone(ModeInfo * mi)
561 {
562   if (anemones == NULL)
563     return;
564 }
565 */
566 
567 XSCREENSAVER_MODULE ("Anemone", anemone)
568 
569 #endif /* MODE_anemone */
570