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 grid_size = get_integer_resource (st->dpy, "size", "Size");
60 if (grid_size < 5) grid_size = 5;
62 size = ((st->xgwa.width > st->xgwa.height
63 ? st->xgwa.width : st->xgwa.height)
65 gw = st->xgwa.width / size;
66 gh = st->xgwa.height / size;
71 th = M_PI / st->sides;
77 th = M_PI / st->sides;
83 th = M_PI / st->sides / 2;
88 th = M_PI / st->sides;
95 gw += 3; /* leave a few extra columns off screen just in case */
100 if (st->initted_p && !st->cells) abort();
101 if (!st->initted_p && st->cells) abort();
103 cells2 = (cell *) calloc (st->ncells, sizeof(*cells2));
104 if (! cells2) abort();
108 for (y = 0; y < (st->gh < gh ? st->gh : gh); y++)
109 for (x = 0; x < (st->gw < gw ? st->gw : gw); x++)
110 cells2[y * gw + x] = st->cells [y * st->gw + x];
120 for (y = 0; y < gh; y++)
121 for (x = 0; x < gw; x++)
123 cell *c = &st->cells[i];
124 c->sides = st->sides;
153 c->cy = y * size * sqrt(3)/2;
158 c->cx = x * size * 2;
159 c->cy = y * size * 2;
162 c->cx = x * size * 0.5;
163 c->cy = y * size * sqrt(3)/2;
164 if ((x & 1) ^ (y & 1))
176 c->speed = st->speed * (st->uniform_p ? 1 : (0.1 + frand(0.9)));
177 c->i = st->lockstep_p ? 0 : random() % r;
178 c->colors[0] = (st->lockstep_p ? 0 : random() % st->ncolors);
183 c->radius += 2; /* Avoid rounding errors */
185 if (c->i > c->radius) c->i = c->radius;
186 if (c->colors[0] >= st->ncolors) c->colors[0] = st->ncolors-1;
187 if (c->colors[1] >= st->ncolors) c->colors[1] = st->ncolors-1;
192 st->initted_p = True;
197 draw_cell (state *st, cell *c)
201 for (j = 0; j <= 1; j++)
203 int r = (j == 0 ? c->radius : c->i);
204 for (i = 0; i < c->sides; i++)
206 double th = i * M_PI * 2 / c->sides;
207 points[i].x = c->cx + r * cos (th + c->th) + 0.5;
208 points[i].y = c->cy + r * sin (th + c->th) + 0.5;
210 XSetForeground (st->dpy, st->gc, st->colors[c->colors[j]].pixel);
211 XFillPolygon (st->dpy, st->window, st->gc, points, c->sides,
212 Convex, CoordModeOrigin);
219 c->colors[1] = c->colors[0];
220 if (c != &st->cells[0])
221 c->colors[0] = st->cells[0].colors[0];
223 c->colors[0] = random() % st->ncolors;
229 hexadrop_init_1 (Display *dpy, Window window, state *st)
236 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
237 st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer");
238 st->speed = get_float_resource (st->dpy, "speed", "Speed");
239 if (st->speed < 0) st->speed = 0;
241 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
243 if (st->ncolors < 2) st->ncolors = 2;
245 st->colors = (XColor *) calloc (sizeof(*st->colors), st->ncolors);
247 if (st->ncolors < 10)
248 make_random_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
249 st->colors, &st->ncolors, False, True, 0, True);
251 make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
252 st->colors, &st->ncolors, True, 0, True);
253 XSetWindowBackground (dpy, window, st->colors[0].pixel);
255 s1 = get_string_resource (st->dpy, "uniform", "Uniform");
256 s2 = get_string_resource (st->dpy, "lockstep", "Lockstep");
258 if ((!s1 || !*s1 || !strcasecmp(s1, "maybe")) &&
259 (!s2 || !*s2 || !strcasecmp(s2, "maybe")))
261 /* When being random, don't do both. */
262 st->uniform_p = random() & 1;
263 st->lockstep_p = st->uniform_p ? 0 : random() & 1;
267 if (!s1 || !*s1 || !strcasecmp(s1, "maybe"))
268 st->uniform_p = random() & 1;
270 st->uniform_p = get_boolean_resource (st->dpy, "uniform", "Uniform");
272 if (!s2 || !*s2 || !strcasecmp(s2, "maybe"))
273 st->lockstep_p = random() & 1;
275 st->lockstep_p = get_boolean_resource (st->dpy, "lockstep","Lockstep");
279 st->sides = get_integer_resource (st->dpy, "sides", "Sides");
280 if (! (st->sides == 0 || st->sides == 3 || st->sides == 4 ||
281 st->sides == 6 || st->sides == 8))
283 printf ("%s: invalid number of sides: %d\n", progname, st->sides);
289 static int defs[] = { 3, 3, 3,
293 st->sides = defs[random() % countof(defs)];
297 gcv.foreground = st->colors[0].pixel;
298 st->gc = XCreateGC (dpy, window, GCForeground, &gcv);
303 hexadrop_init (Display *dpy, Window window)
305 state *st = (state *) calloc (1, sizeof(*st));
306 hexadrop_init_1 (dpy, window, st);
313 hexadrop_draw (Display *dpy, Window window, void *closure)
315 state *st = (state *) closure;
318 for (i = 0; i < st->ncells; i++)
319 draw_cell (st, &st->cells[i]);
326 hexadrop_reshape (Display *dpy, Window window, void *closure,
327 unsigned int w, unsigned int h)
329 state *st = (state *) closure;
330 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
336 hexadrop_free (Display *dpy, Window window, void *closure)
338 state *st = (state *) closure;
341 free_colors (st->xgwa.screen, st->xgwa.colormap, st->colors, st->ncolors);
352 XFreeGC (st->dpy, st->gc);
359 hexadrop_event (Display *dpy, Window window, void *closure, XEvent *event)
361 state *st = (state *) closure;
363 if (screenhack_event_helper (dpy, window, event))
367 hexadrop_free (st->dpy, st->window, st);
370 hexadrop_init_1 (st->dpy, st->window, st);
378 static const char *hexadrop_defaults [] = {
379 ".background: black",
380 ".foreground: white",
390 "*ignoreRotation: True",
395 static XrmOptionDescRec hexadrop_options [] = {
396 { "-delay", ".delay", XrmoptionSepArg, 0 },
397 { "-sides", ".sides", XrmoptionSepArg, 0 },
398 { "-size", ".size", XrmoptionSepArg, 0 },
399 { "-speed", ".speed", XrmoptionSepArg, 0 },
400 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
401 { "-uniform-speed", ".uniform", XrmoptionNoArg, "True" },
402 { "-no-uniform-speed",".uniform", XrmoptionNoArg, "False" },
403 { "-lockstep", ".lockstep", XrmoptionNoArg, "True" },
404 { "-no-lockstep", ".lockstep", XrmoptionNoArg, "False" },
408 XSCREENSAVER_MODULE ("Hexadrop", hexadrop)