began for maemo
[xscreensaver] / xscreensaver / hacks / rorschach.c
1 /* xscreensaver, Copyright (c) 1992, 1996, 1998, 2001, 2006
2  *  Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  * 19971004: Johannes Keukelaar <johannes@nada.kth.se>: Use helix screen
13  *           eraser.
14  */
15
16 #include "screenhack.h"
17 #include "erase.h"
18
19 struct state {
20   GC draw_gc;
21   unsigned int default_fg_pixel;
22   int iterations, offset;
23   Bool xsym, ysym;
24   int sleep_time;
25   int xlim, ylim;
26   XColor color;
27   int current_x, current_y, remaining_iterations;
28   eraser_state *eraser;
29 };
30
31
32 static void *
33 rorschach_init (Display *dpy, Window window)
34 {
35   struct state *st = (struct state *) calloc (1, sizeof(*st));
36   XGCValues gcv;
37   Colormap cmap;
38   XWindowAttributes xgwa;
39   XGetWindowAttributes (dpy, window, &xgwa);
40   cmap = xgwa.colormap;
41   gcv.foreground = st->default_fg_pixel =
42     get_pixel_resource (dpy, cmap, "foreground", "Foreground");
43   st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
44   gcv.foreground = get_pixel_resource (dpy, cmap, "background", "Background");
45   st->iterations = get_integer_resource (dpy, "iterations", "Integer");
46   st->offset = get_integer_resource (dpy, "offset", "Integer");
47   if (st->offset <= 0) st->offset = 3;
48   if (st->iterations < 10) st->iterations = 10;
49   st->sleep_time = get_integer_resource (dpy, "delay", "Delay");
50   st->xsym = get_boolean_resource (dpy, "xsymmetry", "Symmetry");
51   st->ysym = get_boolean_resource (dpy, "ysymmetry", "Symmetry");
52   st->remaining_iterations = -1;
53   st->color.pixel = 0;
54   return st;
55 }
56
57 static void
58 rorschach_reshape (Display *dpy, Window window, void *closure,
59                    unsigned int width, unsigned int height)
60 {
61   struct state *st = (struct state *) closure;
62   st->xlim = width;
63   st->ylim = height;
64 }
65
66
67 static void
68 rorschach_draw_start (Display *dpy, Window window, struct state *st)
69 {
70   Colormap cmap;
71   XWindowAttributes xgwa;
72
73   XGetWindowAttributes (dpy, window, &xgwa);
74   st->xlim = xgwa.width;
75   st->ylim = xgwa.height;
76   cmap = xgwa.colormap;
77
78   if (st->color.pixel) XFreeColors (dpy, cmap, &st->color.pixel, 1, 0);
79
80   if (! mono_p)
81     hsv_to_rgb (random()%360, 1.0, 1.0, &st->color.red, &st->color.green, &st->color.blue);
82   if ((!mono_p) && XAllocColor (dpy, cmap, &st->color))
83     XSetForeground (dpy, st->draw_gc, st->color.pixel);
84   else
85     XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
86
87   st->current_x = st->xlim/2;
88   st->current_y = st->ylim/2;
89   st->remaining_iterations = st->iterations;
90 }
91
92
93 static void
94 rorschach_draw_step (Display *dpy, Window window, struct state *st)
95 {
96 # define ITER_CHUNK 300
97   XPoint points [4 * ITER_CHUNK];
98   int x = st->current_x;
99   int y = st->current_y;
100   int i, j = 0;
101
102   int this_iterations = ITER_CHUNK;
103   if (this_iterations > st->remaining_iterations)
104     this_iterations = st->remaining_iterations;
105
106   for (i = 0; i < this_iterations; i++)
107     {
108       x += ((random () % (1 + (st->offset << 1))) - st->offset);
109       y += ((random () % (1 + (st->offset << 1))) - st->offset);
110       points [j].x = x;
111       points [j].y = y;
112       j++;
113       if (st->xsym)
114         {
115           points [j].x = st->xlim - x;
116           points [j].y = y;
117           j++;
118         }
119       if (st->ysym)
120         {
121           points [j].x = x;
122           points [j].y = st->ylim - y;
123           j++;
124         }
125       if (st->xsym && st->ysym)
126         {
127           points [j].x = st->xlim - x;
128           points [j].y = st->ylim - y;
129           j++;
130         }
131     }
132   XDrawPoints (dpy, window, st->draw_gc, points, j, CoordModeOrigin);
133   st->remaining_iterations -= this_iterations;
134   if (st->remaining_iterations < 0) st->remaining_iterations = 0;
135   st->current_x = x;
136   st->current_y = y;
137 }
138
139
140 static unsigned long
141 rorschach_draw (Display *dpy, Window window, void *closure)
142 {
143   struct state *st = (struct state *) closure;
144   unsigned long delay = 20000;
145
146   if (st->eraser) {
147     st->eraser = erase_window (dpy, window, st->eraser);
148     goto END;
149   }
150
151   if (st->remaining_iterations > 0)
152     {
153       rorschach_draw_step (dpy, window, st);
154       if (st->remaining_iterations == 0)
155         delay = st->sleep_time * 1000000;
156     }
157   else
158     {
159       if (st->remaining_iterations == 0)
160         st->eraser = erase_window (dpy, window, st->eraser);
161
162       rorschach_draw_start (dpy, window, st);
163     }
164  END:
165   return delay;
166 }
167
168
169 static Bool
170 rorschach_event (Display *dpy, Window window, void *closure, XEvent *event)
171 {
172   return False;
173 }
174
175 static void
176 rorschach_free (Display *dpy, Window window, void *closure)
177 {
178   struct state *st = (struct state *) closure;
179   free (st);
180 }
181
182 \f
183 static const char *rorschach_defaults [] = {
184   ".background: black",
185   ".foreground: white",
186   "*xsymmetry:  true",
187   "*ysymmetry:  false",
188   "*iterations: 4000",
189   "*offset:     7",
190   "*delay:      5",
191   0
192 };
193
194 static XrmOptionDescRec rorschach_options [] = {
195   { "-iterations",      ".iterations",  XrmoptionSepArg, 0 },
196   { "-offset",          ".offset",      XrmoptionSepArg, 0 },
197   { "-xsymmetry",       ".xsymmetry",   XrmoptionNoArg, "true" },
198   { "-ysymmetry",       ".ysymmetry",   XrmoptionNoArg, "true" },
199   { "-no-xsymmetry",    ".xsymmetry",   XrmoptionNoArg, "false" },
200   { "-no-ysymmetry",    ".ysymmetry",   XrmoptionNoArg, "false" },
201   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
202   { 0, 0, 0, 0 }
203 };
204
205 XSCREENSAVER_MODULE ("Rorschach", rorschach)