1 /* xscreensaver, Copyright (c) 1999-2014 Jamie Zawinski <jwz@jwz.org>
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
11 * Draws a grid of hexagons or other shapes and drops them out.
16 #include "screenhack.h"
18 #define countof(x) (sizeof(x)/sizeof(*(x)))
19 #define ABS(x) ((x)<0?-(x):(x))
24 double th0, th, radius, i, speed;
32 XWindowAttributes xgwa;
34 int ncells, cells_size, gw, gh;
52 make_cells (state *st)
54 int grid_size = get_integer_resource (st->dpy, "size", "Size");
56 int size, r, gw, gh, x, y, i;
59 if (grid_size < 5) grid_size = 5;
61 size = ((st->xgwa.width > st->xgwa.height
62 ? st->xgwa.width : st->xgwa.height)
64 gw = st->xgwa.width / size;
65 gh = st->xgwa.height / size;
70 th = M_PI / st->sides;
76 th = M_PI / st->sides;
82 th = M_PI / st->sides / 2;
87 th = M_PI / st->sides;
94 gw += 3; /* leave a few extra columns off screen just in case */
99 if (st->initted_p && !st->cells) abort();
100 if (!st->initted_p && st->cells) abort();
102 cells2 = (cell *) calloc (st->ncells, sizeof(*cells2));
103 if (! cells2) abort();
107 for (y = 0; y < (st->gh < gh ? st->gh : gh); y++)
108 for (x = 0; x < (st->gw < gw ? st->gw : gw); x++)
109 cells2[y * gw + x] = st->cells [y * st->gw + x];
119 for (y = 0; y < gh; y++)
120 for (x = 0; x < gw; x++)
122 cell *c = &st->cells[i];
123 c->sides = st->sides;
152 c->cy = y * size * sqrt(3)/2;
157 c->cx = x * size * 2;
158 c->cy = y * size * 2;
161 c->cx = x * size * 0.5;
162 c->cy = y * size * sqrt(3)/2;
163 if ((x & 1) ^ (y & 1))
175 c->speed = st->speed * (st->uniform_p ? 1 : (0.1 + frand(0.9)));
176 c->i = st->lockstep_p ? 0 : random() % r;
177 c->colors[0] = (st->lockstep_p ? 0 : random() % st->ncolors);
182 c->radius += 2; /* Avoid rounding errors */
184 if (c->i > c->radius) c->i = c->radius;
185 if (c->colors[0] >= st->ncolors) c->colors[0] = st->ncolors-1;
186 if (c->colors[1] >= st->ncolors) c->colors[1] = st->ncolors-1;
191 st->initted_p = True;
196 draw_cell (state *st, cell *c)
200 for (j = 0; j <= 1; j++)
202 int r = (j == 0 ? c->radius : c->i);
203 for (i = 0; i < c->sides; i++)
205 double th = i * M_PI * 2 / c->sides;
206 points[i].x = c->cx + r * cos (th + c->th) + 0.5;
207 points[i].y = c->cy + r * sin (th + c->th) + 0.5;
209 XSetForeground (st->dpy, st->gc, st->colors[c->colors[j]].pixel);
210 XFillPolygon (st->dpy, st->window, st->gc, points, c->sides,
211 Convex, CoordModeOrigin);
218 c->colors[1] = c->colors[0];
219 if (c != &st->cells[0])
220 c->colors[0] = st->cells[0].colors[0];
222 c->colors[0] = random() % st->ncolors;
228 hexadrop_init_1 (Display *dpy, Window window, state *st)
235 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
236 st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer");
237 st->speed = get_float_resource (st->dpy, "speed", "Speed");
238 if (st->speed < 0) st->speed = 0;
240 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
242 if (st->ncolors < 2) st->ncolors = 2;
244 st->colors = (XColor *) calloc (sizeof(*st->colors), st->ncolors);
246 if (st->ncolors < 10)
247 make_random_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
248 st->colors, &st->ncolors, False, True, 0, True);
250 make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
251 st->colors, &st->ncolors, True, 0, True);
252 XSetWindowBackground (dpy, window, st->colors[0].pixel);
254 s1 = get_string_resource (st->dpy, "uniform", "Uniform");
255 s2 = get_string_resource (st->dpy, "lockstep", "Lockstep");
257 if ((!s1 || !*s1 || !strcasecmp(s1, "maybe")) &&
258 (!s2 || !*s2 || !strcasecmp(s2, "maybe")))
260 /* When being random, don't do both. */
261 st->uniform_p = random() & 1;
262 st->lockstep_p = st->uniform_p ? 0 : random() & 1;
266 if (!s1 || !*s1 || !strcasecmp(s1, "maybe"))
267 st->uniform_p = random() & 1;
269 st->uniform_p = get_boolean_resource (st->dpy, "uniform", "Uniform");
271 if (!s2 || !*s2 || !strcasecmp(s2, "maybe"))
272 st->lockstep_p = random() & 1;
274 st->lockstep_p = get_boolean_resource (st->dpy, "lockstep","Lockstep");
278 st->sides = get_integer_resource (st->dpy, "sides", "Sides");
279 if (! (st->sides == 0 || st->sides == 3 || st->sides == 4 ||
280 st->sides == 6 || st->sides == 8))
282 printf ("%s: invalid number of sides: %d\n", progname, st->sides);
288 static int defs[] = { 3, 3, 3,
292 st->sides = defs[random() % countof(defs)];
296 gcv.foreground = st->colors[0].pixel;
297 st->gc = XCreateGC (dpy, window, GCForeground, &gcv);
302 hexadrop_init (Display *dpy, Window window)
304 state *st = (state *) calloc (1, sizeof(*st));
305 hexadrop_init_1 (dpy, window, st);
312 hexadrop_draw (Display *dpy, Window window, void *closure)
314 state *st = (state *) closure;
317 for (i = 0; i < st->ncells; i++)
318 draw_cell (st, &st->cells[i]);
325 hexadrop_reshape (Display *dpy, Window window, void *closure,
326 unsigned int w, unsigned int h)
328 state *st = (state *) closure;
329 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
335 hexadrop_free (Display *dpy, Window window, void *closure)
337 state *st = (state *) closure;
340 free_colors (st->xgwa.screen, st->xgwa.colormap, st->colors, st->ncolors);
351 XFreeGC (st->dpy, st->gc);
358 hexadrop_event (Display *dpy, Window window, void *closure, XEvent *event)
360 state *st = (state *) closure;
362 if (screenhack_event_helper (dpy, window, event))
366 hexadrop_free (st->dpy, st->window, st);
369 hexadrop_init_1 (st->dpy, st->window, st);
377 static const char *hexadrop_defaults [] = {
378 ".background: black",
379 ".foreground: white",
389 "*ignoreRotation: True",
394 static XrmOptionDescRec hexadrop_options [] = {
395 { "-delay", ".delay", XrmoptionSepArg, 0 },
396 { "-sides", ".sides", XrmoptionSepArg, 0 },
397 { "-size", ".size", XrmoptionSepArg, 0 },
398 { "-speed", ".speed", XrmoptionSepArg, 0 },
399 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
400 { "-uniform-speed", ".uniform", XrmoptionNoArg, "True" },
401 { "-no-uniform-speed",".uniform", XrmoptionNoArg, "False" },
402 { "-lockstep", ".lockstep", XrmoptionNoArg, "True" },
403 { "-no-lockstep", ".lockstep", XrmoptionNoArg, "False" },
407 XSCREENSAVER_MODULE ("Hexadrop", hexadrop)