summaryrefslogtreecommitdiffstats
path: root/hacks/substrate.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/substrate.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/substrate.c')
-rw-r--r--hacks/substrate.c773
1 files changed, 773 insertions, 0 deletions
diff --git a/hacks/substrate.c b/hacks/substrate.c
new file mode 100644
index 0000000..278a3bd
--- /dev/null
+++ b/hacks/substrate.c
@@ -0,0 +1,773 @@
+/*
+ * Substrate (dragorn@kismetwireless.net)
+ * Directly ported code from complexification.net Substrate art
+ * http://complexification.net/gallery/machines/substrate/applet_s/substrate_s.pde
+ *
+ * Substrate code:
+ * j.tarbell June, 2004
+ * Albuquerque, New Mexico
+ * complexification.net
+ *
+ * CHANGES
+ *
+ * 1.1 dragorn Jan 04 2005 Fixed some indenting, typo in errors for parsing
+ * cmdline args
+ * 1.1 dagraz Jan 04 2005 Added option for circular cracks (David Agraz)
+ * Cleaned up issues with timeouts in start_crack (DA)
+ * 1.0 dragorn Oct 10 2004 First port done
+ *
+ * Directly based the hacks of:
+ *
+ * xscreensaver, Copyright (c) 1997, 1998, 2002 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+
+/* this program goes faster if some functions are inline. The following is
+ * borrowed from ifs.c */
+#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
+#undef inline
+#define inline /* */
+#endif
+
+#define STEP 0.42
+
+/* Raw colormap extracted from pollockEFF.gif */
+static const char *rgb_colormap[] = {
+ "#201F21", "#262C2E", "#352626", "#372B27",
+ "#302C2E", "#392B2D", "#323229", "#3F3229",
+ "#38322E", "#2E333D", "#333A3D", "#473329",
+ "#40392C", "#40392E", "#47402C", "#47402E",
+ "#4E402C", "#4F402E", "#4E4738", "#584037",
+ "#65472D", "#6D5D3D", "#745530", "#755532",
+ "#745D32", "#746433", "#7C6C36", "#523152",
+ "#444842", "#4C5647", "#655D45", "#6D5D44",
+ "#6C5D4E", "#746C43", "#7C6C42", "#7C6C4B",
+ "#6B734B", "#73734B", "#7B7B4A", "#6B6C55",
+ "#696D5E", "#7B6C5D", "#6B7353", "#6A745D",
+ "#727B52", "#7B7B52", "#57746E", "#687466",
+ "#9C542B", "#9D5432", "#9D5B35", "#936B36",
+ "#AA7330", "#C45A27", "#D95223", "#D85A20",
+ "#DB5A23", "#E57037", "#836C4B", "#8C6B4B",
+ "#82735C", "#937352", "#817B63", "#817B6D",
+ "#927B63", "#D9893B", "#E49832", "#DFA133",
+ "#E5A037", "#F0AB3B", "#8A8A59", "#B29A58",
+ "#89826B", "#9A8262", "#888B7C", "#909A7A",
+ "#A28262", "#A18A69", "#A99968", "#99A160",
+ "#99A168", "#CA8148", "#EB8D43", "#C29160",
+ "#C29168", "#D1A977", "#C9B97F", "#F0E27B",
+ "#9F928B", "#C0B999", "#E6B88F", "#C8C187",
+ "#E0C886", "#F2CC85", "#F5DA83", "#ECDE9D",
+ "#F5D294", "#F5DA94", "#F4E784", "#F4E18A",
+ "#F4E193", "#E7D8A7", "#F1D4A5", "#F1DCA5",
+ "#F4DBAD", "#F1DCAE", "#F4DBB5", "#F5DBBD",
+ "#F4E2AD", "#F5E9AD", "#F4E3BE", "#F5EABE",
+ "#F7F0B6", "#D9D1C1", "#E0D0C0", "#E7D8C0",
+ "#F1DDC6", "#E8E1C0", "#F3EDC7", "#F6ECCE",
+ "#F8F2C7", "#EFEFD0", 0
+};
+
+typedef struct {
+ /* Synthesis of data from Crack:: and SandPainter:: */
+ float x, y;
+ float t;
+ float ys, xs, t_inc; /* for curvature calculations */
+
+ int curved;
+
+ unsigned long sandcolor;
+ float sandp, sandg;
+
+ float degrees_drawn;
+
+ int crack_num;
+
+} crack;
+
+struct field {
+ unsigned int height;
+ unsigned int width;
+
+ unsigned int initial_cracks;
+
+ unsigned int num;
+ unsigned int max_num;
+
+ int grains; /* number of grains in the sand painting */
+
+ int circle_percent;
+
+ crack *cracks; /* grid of cracks */
+ int *cgrid; /* grid of actual crack placement */
+
+ /* Raw map of pixels we need to keep for alpha blending */
+ unsigned long int *off_img;
+
+ /* color parms */
+ int numcolors;
+ unsigned long *parsedcolors;
+ unsigned long fgcolor;
+ unsigned long bgcolor;
+ int visdepth;
+
+ unsigned int cycles;
+
+ unsigned int wireframe;
+ unsigned int seamless;
+};
+
+struct state {
+ Display *dpy;
+ Window window;
+
+ struct field *f;
+ unsigned int max_cycles;
+ int growth_delay;
+ GC fgc;
+ XWindowAttributes xgwa;
+ XGCValues gcv;
+};
+
+
+static void
+*xrealloc(void *p, size_t size)
+{
+ void *ret;
+ if ((ret = realloc(p, size)) == NULL) {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ exit(1);
+ }
+ return ret;
+}
+
+static struct field
+*init_field(void)
+{
+ struct field *f = xrealloc(NULL, sizeof(struct field));
+ f->height = 0;
+ f->width = 0;
+ f->initial_cracks = 0;
+ f->num = 0;
+ f->max_num = 0;
+ f->cracks = NULL;
+ f->cgrid = NULL;
+ f->off_img = NULL;
+ f->numcolors = 0;
+ f->parsedcolors = NULL;
+ f->cycles = 0;
+ f->wireframe = 0;
+ f->seamless = 0;
+ f->fgcolor = 0;
+ f->bgcolor = 0;
+ f->visdepth = 0;
+ f->grains = 0;
+ f->circle_percent = 0;
+ return f;
+}
+
+/* Quick references to pixels in the offscreen map and in the crack grid */
+#define ref_pixel(f, x, y) ((f)->off_img[(y) * (f)->width + (x)])
+#define ref_cgrid(f, x, y) ((f)->cgrid[(y) * (f)->width + (x)])
+
+static inline void start_crack(struct field *f, crack *cr)
+{
+ /* synthesis of Crack::findStart() and crack::startCrack() */
+ int px = 0;
+ int py = 0;
+ int found = 0;
+ int timeout = 0;
+ float a;
+
+ /* shift until crack is found */
+ while ((!found) && (timeout++ < 10000)) {
+ px = (int) (random() % f->width);
+ py = (int) (random() % f->height);
+
+ if (ref_cgrid(f, px, py) < 10000)
+ found = 1;
+ }
+
+ if ( !found ) {
+ /* We timed out. Use our default values */
+ px = cr->x;
+ py = cr->y;
+
+ /* Sanity check needed */
+ if (px < 0) px = 0;
+ if (px >= f->width) px = f->width - 1;
+ if (py < 0) py = 0;
+ if (py >= f->height) py = f->height - 1;
+
+ ref_cgrid(f, px, py) = cr->t;
+ }
+
+ /* start a crack */
+ a = ref_cgrid(f, px, py);
+
+ if ((random() % 100) < 50) {
+ /* conversion of the java int(random(-2, 2.1)) */
+ a -= 90 + (frand(4.1) - 2.0);
+ } else {
+ a += 90 + (frand(4.1) - 2.0);
+ }
+
+ if ((random() % 100) < f->circle_percent) {
+ float r; /* radius */
+ float radian_inc;
+
+ cr->curved = 1;
+ cr->degrees_drawn = 0;
+
+ r = 10 + (random() % ((f->width + f->height) / 2));
+
+ if ((random() % 100) < 50) {
+ r *= -1;
+ }
+
+ /* arc length = r * theta => theta = arc length / r */
+ radian_inc = STEP / r;
+ cr->t_inc = radian_inc * 360 / 2 / M_PI;
+
+ cr->ys = r * sin(radian_inc);
+ cr->xs = r * ( 1 - cos(radian_inc));
+
+ }
+ else {
+ cr->curved = 0;
+ }
+
+ /* Condensed from Crack::startCrack */
+ cr->x = px + ((float) 0.61 * cos(a * M_PI / 180));
+ cr->y = py + ((float) 0.61 * sin(a * M_PI / 180));
+ cr->t = a;
+
+}
+
+static inline void make_crack(struct field *f)
+{
+ crack *cr;
+
+ if (f->num < f->max_num) {
+ /* make a new crack */
+ f->cracks = (crack *) xrealloc(f->cracks, sizeof(crack) * (f->num + 1));
+
+ cr = &(f->cracks[f->num]);
+ /* assign colors */
+ cr->sandp = 0;
+ cr->sandg = (frand(0.2) - 0.01);
+ cr->sandcolor = f->parsedcolors[random() % f->numcolors];
+ cr->crack_num = f->num;
+ cr->curved = 0;
+ cr->degrees_drawn = 0;
+
+ /* We could use these values in the timeout case of start_crack */
+
+ cr->x = random() % f->width;
+ cr->y = random() % f->height;
+ cr->t = random() % 360;
+
+ /* start it */
+ start_crack(f, cr);
+
+ f->num++;
+ }
+}
+
+static inline void point2rgb(int depth, unsigned long c, int *r, int *g, int *b)
+{
+ switch(depth) {
+ case 32:
+ case 24:
+#ifdef HAVE_JWXYZ
+ /* This program idiotically does not go through a color map, so
+ we have to hardcode in knowledge of how jwxyz.a packs pixels!
+ Fix it to go through st->colors[st->ncolors] instead!
+ */
+ *r = (c & 0x00ff0000) >> 16;
+ *g = (c & 0x0000ffff) >> 8;
+ *b = (c & 0x000000ff);
+#else
+ *g = (c & 0xff00) >> 8;
+ *r = (c & 0xff0000) >> 16;
+ *b = c & 0xff;
+#endif
+ break;
+ case 16:
+ *g = ((c >> 5) & 0x3f) << 2;
+ *r = ((c >> 11) & 0x1f) << 3;
+ *b = (c & 0x1f) << 3;
+ break;
+ case 15:
+ *g = ((c >> 5) & 0x1f) << 3;
+ *r = ((c >> 10) & 0x1f) << 3;
+ *b = (c & 0x1f) << 3;
+ break;
+ }
+}
+
+static inline unsigned long rgb2point(int depth, int r, int g, int b)
+{
+ unsigned long ret = 0;
+
+ switch(depth) {
+ case 32:
+ case 24:
+#ifdef HAVE_JWXYZ
+ /* This program idiotically does not go through a color map, so
+ we have to hardcode in knowledge of how jwxyz.a packs pixels!
+ Fix it to go through st->colors[st->ncolors] instead!
+ */
+ ret = 0xFF000000 | (r << 16) | (g << 8) | b;
+#else
+ ret |= (r << 16) | (g << 8) | b;
+#endif
+ break;
+ case 16:
+ ret = ((r>>3) << 11) | ((g>>2)<<5) | (b>>3);
+ break;
+ case 15:
+ ret = ((r>>3) << 10) | ((g>>3)<<5) | (b>>3);
+ break;
+ }
+
+ return ret;
+}
+
+/* alpha blended point drawing -- this is Not Right and will likely fail on
+ * non-intel platforms as it is now, needs fixing */
+static inline unsigned long
+trans_point(struct state *st,
+ int x1, int y1, unsigned long myc, float a,
+ struct field *f)
+{
+ if ((x1 >= 0) && (x1 < f->width) && (y1 >= 0) && (y1 < f->height)) {
+ if (a >= 1.0) {
+ ref_pixel(f, x1, y1) = myc;
+ } else {
+ int or = 0, og = 0, ob = 0;
+ int r = 0, g = 0, b = 0;
+ int nr, ng, nb;
+ unsigned long c;
+
+ c = ref_pixel(f, x1, y1);
+
+ point2rgb(f->visdepth, c, &or, &og, &ob);
+ point2rgb(f->visdepth, myc, &r, &g, &b);
+
+ nr = or + (r - or) * a;
+ ng = og + (g - og) * a;
+ nb = ob + (b - ob) * a;
+
+ c = rgb2point(f->visdepth, nr, ng, nb);
+
+ ref_pixel(f, x1, y1) = c;
+
+ return c;
+ }
+ }
+
+ return f->bgcolor;
+}
+
+static inline void
+region_color(struct state *st, GC fgc, struct field *f, crack *cr)
+{
+ /* synthesis of Crack::regionColor() and SandPainter::render() */
+
+ float rx = cr->x;
+ float ry = cr->y;
+ int openspace = 1;
+ int cx, cy;
+ float maxg;
+ int grains, i;
+ float w;
+ float drawx, drawy;
+ unsigned long c;
+
+ while (openspace) {
+ /* move perpendicular to crack */
+ rx += (0.81 * sin(cr->t * M_PI/180));
+ ry -= (0.81 * cos(cr->t * M_PI/180));
+
+ cx = (int) rx;
+ cy = (int) ry;
+ if (f->seamless) {
+ cx %= f->width;
+ cy %= f->height;
+ }
+
+ if ((cx >= 0) && (cx < f->width) && (cy >= 0) && (cy < f->height)) {
+ /* safe to check */
+ if (f->cgrid[cy * f->width + cx] > 10000) {
+ /* space is open */
+ } else {
+ openspace = 0;
+ }
+ } else {
+ openspace = 0;
+ }
+ }
+
+ /* SandPainter stuff here */
+
+ /* Modulate gain */
+ cr->sandg += (frand(0.1) - 0.050);
+ maxg = 1.0;
+
+ if (cr->sandg < 0)
+ cr->sandg = 0;
+
+ if (cr->sandg > maxg)
+ cr->sandg = maxg;
+
+ grains = f->grains;
+
+ /* Lay down grains of sand */
+ w = cr->sandg / (grains - 1);
+
+ for (i = 0; i < grains; i++) {
+ drawx = (cr->x + (rx - cr->x) * sin(cr->sandp + sin((float) i * w)));
+ drawy = (cr->y + (ry - cr->y) * sin(cr->sandp + sin((float) i * w)));
+ if (f->seamless) {
+ drawx = fmod(drawx + f->width, f->width);
+ drawy = fmod(drawy + f->height, f->height);
+ }
+
+ /* Draw sand bit */
+ c = trans_point(st, drawx, drawy, cr->sandcolor, (0.1 - i / (grains * 10.0)), f);
+
+ XSetForeground(st->dpy, fgc, c);
+ XDrawPoint(st->dpy, st->window, fgc, (int) drawx, (int) drawy);
+ XSetForeground(st->dpy, fgc, f->fgcolor);
+ }
+}
+
+static void build_substrate(struct field *f)
+{
+ int tx;
+ /* int ty; */
+
+ f->cycles = 0;
+
+ if (f->cgrid) {
+ free(f->cgrid);
+ f->cgrid = NULL;
+ }
+
+ if (f->cracks) {
+ free(f->cracks);
+ f->cracks = NULL;
+ }
+
+ f->num = 0;
+
+ /* erase the crack grid */
+ f->cgrid = (int *) xrealloc(f->cgrid, sizeof(int) * f->height * f->width);
+ {
+ int j;
+ int *p = f->cgrid;
+ for (j = 0; j < f->height * f->width; j++)
+ *p++ = 10001;
+ }
+
+ /* Not necessary now that make_crack ensures we have usable default
+ * values in start_crack's timeout case
+ * make random crack seeds *
+ for (tx = 0; tx < 16; tx++) {
+ ty = (int) (random() % (f->width * f->height - 1));
+ f->cgrid[ty] = (int) random() % 360;
+ }
+ */
+
+ /* make the initial cracks */
+ for (tx = 0; tx < f->initial_cracks; tx++)
+ make_crack(f);
+}
+
+
+static inline void
+movedrawcrack(struct state *st, GC fgc, struct field *f, int cracknum)
+{
+ /* Basically Crack::move() */
+
+ int cx, cy;
+ crack *cr = &(f->cracks[cracknum]);
+
+ /* continue cracking */
+ if ( !cr->curved ) {
+ cr->x += ((float) STEP * cos(cr->t * M_PI/180));
+ cr->y += ((float) STEP * sin(cr->t * M_PI/180));
+ }
+ else {
+ cr->x += ((float) cr->ys * cos(cr->t * M_PI/180));
+ cr->y += ((float) cr->ys * sin(cr->t * M_PI/180));
+
+ cr->x += ((float) cr->xs * cos(cr->t * M_PI/180 - M_PI / 2));
+ cr->y += ((float) cr->xs * sin(cr->t * M_PI/180 - M_PI / 2));
+
+ cr->t += cr->t_inc;
+ cr->degrees_drawn += fabsf(cr->t_inc);
+ }
+ if (f->seamless) {
+ cr->x = fmod(cr->x + f->width, f->width);
+ cr->y = fmod(cr->y + f->height, f->height);
+ }
+
+ /* bounds check */
+ /* modification of random(-0.33,0.33) */
+ cx = (int) (cr->x + (frand(0.66) - 0.33));
+ cy = (int) (cr->y + (frand(0.66) - 0.33));
+ if (f->seamless) {
+ cx %= f->width;
+ cy %= f->height;
+ }
+
+ if ((cx >= 0) && (cx < f->width) && (cy >= 0) && (cy < f->height)) {
+ /* draw sand painter if we're not wireframe */
+ if (!f->wireframe)
+ region_color(st, fgc, f, cr);
+
+ /* draw fgcolor crack */
+ ref_pixel(f, cx, cy) = f->fgcolor;
+ XDrawPoint(st->dpy, st->window, fgc, cx, cy);
+
+ if ( cr->curved && (cr->degrees_drawn > 360) ) {
+ /* completed the circle, stop cracking */
+ start_crack(f, cr); /* restart ourselves */
+ make_crack(f); /* generate a new crack */
+ }
+ /* safe to check */
+ else if ((f->cgrid[cy * f->width + cx] > 10000) ||
+ (fabsf(f->cgrid[cy * f->width + cx] - cr->t) < 5)) {
+ /* continue cracking */
+ f->cgrid[cy * f->width + cx] = (int) cr->t;
+ } else if (fabsf(f->cgrid[cy * f->width + cx] - cr->t) > 2) {
+ /* crack encountered (not self), stop cracking */
+ start_crack(f, cr); /* restart ourselves */
+ make_crack(f); /* generate a new crack */
+ }
+ } else {
+ /* out of bounds, stop cracking */
+
+ /* need these in case of timeout in start_crack */
+ cr->x = random() % f->width;
+ cr->y = random() % f->height;
+ cr->t = random() % 360;
+
+ start_crack(f, cr); /* restart ourselves */
+ make_crack(f); /* generate a new crack */
+ }
+
+}
+
+
+static void build_img(Display *dpy, Window window, XWindowAttributes xgwa, GC fgc,
+ struct field *f)
+{
+ if (f->off_img) {
+ free(f->off_img);
+ f->off_img = NULL;
+ }
+
+ f->off_img = (unsigned long *) xrealloc(f->off_img, sizeof(unsigned long) *
+ f->width * f->height);
+
+ memset(f->off_img, f->bgcolor, sizeof(unsigned long) * f->width * f->height);
+}
+
+
+static void *
+substrate_init (Display *dpy, Window window)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ XColor tmpcolor;
+
+ st->dpy = dpy;
+ st->window = window;
+ st->f = init_field();
+
+ st->growth_delay = (get_integer_resource(st->dpy, "growthDelay", "Integer"));
+ st->max_cycles = (get_integer_resource(st->dpy, "maxCycles", "Integer"));
+ st->f->initial_cracks = (get_integer_resource(st->dpy, "initialCracks", "Integer"));
+ st->f->max_num = (get_integer_resource(st->dpy, "maxCracks", "Integer"));
+ st->f->wireframe = (get_boolean_resource(st->dpy, "wireFrame", "Boolean"));
+ st->f->grains = (get_integer_resource(st->dpy, "sandGrains", "Integer"));
+ st->f->circle_percent = (get_integer_resource(st->dpy, "circlePercent", "Integer"));
+ st->f->seamless = (get_boolean_resource(st->dpy, "seamless", "Boolean"));
+
+ if (st->f->initial_cracks <= 2) {
+ fprintf(stderr, "%s: Initial cracks must be greater than 2\n", progname);
+ exit (1);
+ }
+
+ if (st->f->max_num <= 10) {
+ fprintf(stderr, "%s: Maximum number of cracks must be less than 10\n",
+ progname);
+ exit (1);
+ }
+
+ if (st->f->circle_percent < 0) {
+ fprintf(stderr, "%s: circle percent must be at least 0\n", progname);
+ exit (1);
+ }
+
+ if (st->f->circle_percent > 100) {
+ fprintf(stderr, "%s: circle percent must be less than 100\n", progname);
+ exit (1);
+ }
+
+ XGetWindowAttributes(st->dpy, st->window, &st->xgwa);
+
+ st->f->height = st->xgwa.height;
+ st->f->width = st->xgwa.width;
+ st->f->visdepth = st->xgwa.depth;
+
+ /* Count the colors in our map and assign them in a horrifically inefficient
+ * manner but it only happens once */
+ while (rgb_colormap[st->f->numcolors] != NULL) {
+ st->f->parsedcolors = (unsigned long *) xrealloc(st->f->parsedcolors,
+ sizeof(unsigned long) *
+ (st->f->numcolors + 1));
+ if (!XParseColor(st->dpy, st->xgwa.colormap, rgb_colormap[st->f->numcolors], &tmpcolor)) {
+ fprintf(stderr, "%s: couldn't parse color %s\n", progname,
+ rgb_colormap[st->f->numcolors]);
+ exit(1);
+ }
+
+ if (!XAllocColor(st->dpy, st->xgwa.colormap, &tmpcolor)) {
+ fprintf(stderr, "%s: couldn't allocate color %s\n", progname,
+ rgb_colormap[st->f->numcolors]);
+ exit(1);
+ }
+
+ st->f->parsedcolors[st->f->numcolors] = tmpcolor.pixel;
+
+ st->f->numcolors++;
+ }
+
+ st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap,
+ "foreground", "Foreground");
+ st->gcv.background = get_pixel_resource(st->dpy, st->xgwa.colormap,
+ "background", "Background");
+ st->fgc = XCreateGC(st->dpy, st->window, GCForeground, &st->gcv);
+
+ st->f->fgcolor = st->gcv.foreground;
+ st->f->bgcolor = st->gcv.background;
+
+ /* Initialize stuff */
+ build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f);
+ build_substrate(st->f);
+
+ return st;
+}
+
+static unsigned long
+substrate_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ int tempx;
+
+ if ((st->f->cycles % 10) == 0) {
+
+ /* Restart if the window size changes */
+ XGetWindowAttributes(st->dpy, st->window, &st->xgwa);
+
+ if (st->f->height != st->xgwa.height || st->f->width != st->xgwa.width) {
+ st->f->height = st->xgwa.height;
+ st->f->width = st->xgwa.width;
+ st->f->visdepth = st->xgwa.depth;
+
+ build_substrate(st->f);
+ build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f);
+ XSetForeground(st->dpy, st->fgc, st->gcv.background);
+ XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height);
+ XSetForeground(st->dpy, st->fgc, st->gcv.foreground);
+ }
+ }
+
+ for (tempx = 0; tempx < st->f->num; tempx++) {
+ movedrawcrack(st, st->fgc, st->f, tempx);
+ }
+
+ st->f->cycles++;
+
+ if (st->f->cycles >= st->max_cycles && st->max_cycles != 0) {
+ build_substrate(st->f);
+ build_img(st->dpy, st->window, st->xgwa, st->fgc, st->f);
+ XSetForeground(st->dpy, st->fgc, st->gcv.background);
+ XFillRectangle(st->dpy, st->window, st->fgc, 0, 0, st->xgwa.width, st->xgwa.height);
+ XSetForeground(st->dpy, st->fgc, st->gcv.foreground);
+ }
+
+ /* #### mi->recursion_depth = st->f->cycles; */
+ return st->growth_delay;
+}
+
+
+static void
+substrate_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+substrate_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ struct state *st = (struct state *) closure;
+ if (screenhack_event_helper (dpy, window, event))
+ {
+ st->f->cycles = st->max_cycles;
+ return True;
+ }
+ return False;
+}
+
+static void
+substrate_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
+}
+
+static const char *substrate_defaults[] = {
+ ".background: white",
+ ".foreground: black",
+ "*fpsSolid: true",
+ "*wireFrame: false",
+ "*seamless: false",
+ "*maxCycles: 10000",
+ "*growthDelay: 18000",
+ "*initialCracks: 3",
+ "*maxCracks: 100",
+ "*sandGrains: 64",
+ "*circlePercent: 33",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+ 0
+};
+
+static XrmOptionDescRec substrate_options[] = {
+ {"-background", ".background", XrmoptionSepArg, 0},
+ {"-foreground", ".foreground", XrmoptionSepArg, 0},
+ {"-wireframe", ".wireFrame", XrmoptionNoArg, "true"},
+ {"-seamless", ".seamless", XrmoptionNoArg, "true"},
+ {"-max-cycles", ".maxCycles", XrmoptionSepArg, 0},
+ {"-growth-delay", ".growthDelay", XrmoptionSepArg, 0},
+ {"-initial-cracks", ".initialCracks", XrmoptionSepArg, 0},
+ {"-max-cracks", ".maxCracks", XrmoptionSepArg, 0},
+ {"-sand-grains", ".sandGrains", XrmoptionSepArg, 0},
+ {"-circle-percent", ".circlePercent", XrmoptionSepArg, 0},
+ {0, 0, 0, 0}
+};
+
+XSCREENSAVER_MODULE ("Substrate", substrate)