From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/interaggregate.c | 981 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 981 insertions(+) create mode 100644 hacks/interaggregate.c (limited to 'hacks/interaggregate.c') diff --git a/hacks/interaggregate.c b/hacks/interaggregate.c new file mode 100644 index 0000000..6308841 --- /dev/null +++ b/hacks/interaggregate.c @@ -0,0 +1,981 @@ +/* + * InterAggregate (dagraz@gmail.com) + * Based on code from complexification.net Intersection Aggregate + * http://www.complexification.net/gallery/machines/interAggregate/index.php + * + * Intersection Aggregate code: + * j.tarbell May, 2004 + * Albuquerque, New Mexico + * complexification.net + * + * Also based on substrate, a port of j.tarbell's Substrate Art done + * by dragorn@kismetwireless.net + * + * + * Interesting command line options, all of which serve to + * concentrate the painting in some way: + * + * -percent-orbits 100 -base-orbits 50 -base-on-center -growth-delay 0 + * + * Paint should be concentrated in the center of the canvas, orbiting + * about it. -percent-orbits 100 implies -base-on-center, so that's + * not really needed. + * + * + * -percent-orbits 99 -base-orbits 50 -growth-delay 0 + * + * Like the above example, but the 'center' will rove about the screen. + * + * -percent-orbits 98 -base-orbits 50 -growth-delay 0 + * + * Like the above example, but there will be two roving centers. + * + * + * TODO: + * -fix alpha blending / byte ordering + * + * CHANGES + * + * + * Directly based the hacks of: + * + * xscreensaver, Copyright (c) 1997, 1998, 2002 Jamie Zawinski + * + * 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 +#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 + +#ifndef MIN +#define MIN(x,y) ((x < y) ? x : y) +#endif + +#ifndef MAX +#define MAX(x,y) ((x < y) ? y : x) +#endif + +static const char *interaggregate_defaults[] = +{ + ".background: white", + ".foreground: black", + "*fpsSolid: true", + "*maxCycles: 100000", +#ifdef TIME_ME + "*growthDelay: 0", +#else + "*growthDelay: 18000", +#endif + "*numCircles: 100", + "*percentOrbits: 0", + "*baseOrbits: 75", + "*baseOnCenter: False", + "*drawCenters: False", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec interaggregate_options[] = +{ + {"-background", ".background", XrmoptionSepArg, 0}, + {"-foreground", ".foreground", XrmoptionSepArg, 0}, + {"-max-cycles", ".maxCycles", XrmoptionSepArg, 0}, + {"-growth-delay", ".growthDelay", XrmoptionSepArg, 0}, + {"-num-circles", ".numCircles", XrmoptionSepArg, 0}, + {"-percent-orbits", ".percentOrbits", XrmoptionSepArg, 0}, + {"-base-orbits", ".baseOrbits", XrmoptionSepArg, 0}, + {"-base-on-center", ".baseOnCenter", XrmoptionNoArg, "true"}, + {"-draw-centers", ".drawCenters", XrmoptionNoArg, "true"}, + {0, 0, 0, 0} +}; + +/* Raw colormap extracted from pollockEFF.gif */ +#if 0 +char *rgb_colormap[] = +{ + "#FFFFFF", /* white */ + "#000000", /* black */ + "#000000", /* more black */ + /* "#736451", */ + "#4e3e2e", /* olive */ + /* "#666666", */ + "#694d35", /* camel */ + "#b9a88c", /* tan */ + 0 +}; +#endif + +static const char *rgb_colormap[] = +{ + "#FFFFFF", /* white */ + "#000000", /* more black */ + "#000000", /* more black */ + "#4e3e2e", /* olive */ + "#694d35", /* camel */ + "#b0a085", /* tan */ + "#e6d3ae", + 0 +}; + +/* black white brown olive grey camel */ + +typedef enum { LINEAR, ORBIT } PathType; + +typedef struct +{ + + unsigned long color; + double gain; + double p; + +} SandPainter; + +typedef struct _circle +{ + double radius; + + double x; + double y; + + PathType path_type; + + /* for a linear path */ + double dx; + double dy; + + /* for orbital path */ + double theta; + double r; + double dtheta; + + struct _circle* center; + + int num_painters; + SandPainter* painters; + +} Circle; + + +struct field +{ + int height; + int width; + + int num_circles; + Circle* circles; + + int percent_orbits; + int base_orbits; + Bool base_on_center; + + /* used for orbits circling the center of the screen */ + Circle center_of_universe; + + /* 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; + + double max_gain; + + /* for debugging */ + Bool draw_centers; + + /* for profiling whatnot */ + int possible_intersections; + int intersection_count; +}; + + +static struct field * +init_field(void) +{ + struct field *f = (struct field*) malloc(sizeof(struct field)); + if ( f == NULL ) + { + fprintf(stderr, "%s: Failed to allocate field!\n", progname); + exit(1); + } + + f->height = 0; + f->width = 0; + f->num_circles = 0; + f->circles = NULL; + f->percent_orbits = 0; + f->base_orbits = 0; + f->base_on_center = False; + f->off_img = NULL; + f->numcolors = 0; + f->parsedcolors = NULL; + f->fgcolor = 0; + f->bgcolor = 0; + f->visdepth = 0; + + f->cycles = 0; + + f->max_gain = 0.22; + + f->draw_centers = False; + + f->possible_intersections = 0; + f->intersection_count = 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 in_bounds(f, x, y) ((x >= 0) && (x < f->width) && (y >= 0) && (y < f->height)) + +/* Consider rewriting with XQueryColor, or ImageByteOrder */ + +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 + *b = c & 0xff; + *g = (c & 0xff00) >> 8; + *r = (c & 0xff0000) >> 16; +#endif + break; + case 16: + *b = (int) (c & 0x1f) << 3; + *g = (int) ((c >> 5) & 0x3f) << 2; + *r = (int) ((c >> 11) & 0x1f) << 3; + break; + case 15: + *b = (int) (c & 0x1f) << 3; + *g = (int) ((c >> 5) & 0x1f) << 3; + *r = (int) ((c >> 10) & 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(int x1, int y1, unsigned long myc, double a, + struct field *f) +{ + if (a >= 1.0) + { + ref_pixel(f, x1, y1) = myc; + return 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; + } +} + +static inline void drawPoint(int x, int y, unsigned long color, double intensity, + Display *dpy, Window window, GC fgc, struct field *f) + +{ + unsigned long c; + + while ( x >= f->width ) x -= f->width; + while ( x < 0 ) x += f->width; + + while ( y >= f->height ) y -= f->height; + while ( y < 0 ) y += f->height; + + /* if ( in_bounds(f, x, y) ) ... */ + + c = trans_point(x, y, color, intensity, f); + + XSetForeground(dpy, fgc, c); + XDrawPoint(dpy, window, fgc, x, y); +} + +static inline void paint(SandPainter* painter, double ax, double ay, double bx, double by, + Display *dpy, Window window, GC fgc, + struct field *f) +{ + /* the sand painter */ + + double inc, sandp; + int i; + + /* XXX try adding tpoint here, like orig */ + + /* jitter the painter's values */ + painter->gain += frand(0.05) - 0.025; + + if ( painter->gain > f->max_gain ) + painter->gain = -f->max_gain; + else if ( painter->gain < -f->max_gain ) + painter->gain = f->max_gain; + + painter->p += frand(0.1) - 0.05; + + if ( 0 < painter->p ) + painter->p = 0; + else if ( painter->p > 1.0 ) + painter->p = 1.0; + + /* replace 0.1 with 1 / f->grains */ + inc = painter->gain * 0.1; + sandp = 0; + + for(i = 0; i <= 10; ++i) + { + int drawx, drawy; + double sp, sm; + double intensity = 0.1 - 0.009 * i; + + sp = sin(painter->p + sandp); + drawx = ax + (bx - ax) * sp; + drawy = ay + (by - ay) * sp; + + drawPoint(drawx, drawy, painter->color, + intensity, + dpy, window, fgc, f); + + sm = sin(painter->p - sandp); + drawx = ax + (bx - ax) * sm; + drawy = ay + (by - ay) * sm; + + drawPoint(drawx, drawy, painter->color, + intensity, + dpy, window, fgc, f); + + sandp += inc; + } +} + +static void build_colors(struct field *f, Display *dpy, XWindowAttributes *xgwa) +{ + + XColor tmpcolor; + int i; + /* Count the colors in our map and assign them in a horrifically inefficient + * manner but it only happens once */ + + for( f->numcolors = 0; + rgb_colormap[f->numcolors] != NULL; + ++f->numcolors ) + { + ; + } + + if (f->numcolors < 1) f->numcolors = 1; + f->parsedcolors = (unsigned long *) calloc(f->numcolors, + sizeof(unsigned long)); + if ( f->parsedcolors == NULL ) + { + fprintf(stderr, "%s: Failed to allocate parsedcolors\n", + progname); + exit(1); + } + + for(i = 0; i < f->numcolors; ++i) + { + if (!XParseColor(dpy, xgwa->colormap, + rgb_colormap[i], &tmpcolor)) + { + fprintf(stderr, "%s: couldn't parse color %s\n", progname, + rgb_colormap[i]); + exit(1); + } + + if (!XAllocColor(dpy, xgwa->colormap, &tmpcolor)) + { + fprintf(stderr, "%s: couldn't allocate color %s\n", progname, + rgb_colormap[i]); + exit(1); + } + + f->parsedcolors[i] = tmpcolor.pixel; + + } +} + +/* used when the window is resized */ +static void build_img(struct field *f) +{ + if (f->off_img) { + free(f->off_img); + f->off_img = NULL; + } + + f->off_img = (unsigned long *) calloc(f->width * f->height, + sizeof(unsigned long)); + + + if ( f->off_img == NULL ) + { + fprintf(stderr, "%s: Failed to allocate off_img\n", + progname); + exit(1); + } + + memset(f->off_img, f->bgcolor, + sizeof(unsigned long) * f->width * f->height); +} + +static void free_circles(struct field *f) +{ + int i; + + if ( f->circles != NULL ) + { + for(i = 0; i < f->num_circles; ++i) + { + free (f->circles[i].painters); + } + + free (f->circles); + f->circles = NULL; + } +} + +static void build_field(Display *dpy, Window window, XWindowAttributes xgwa, GC fgc, + struct field *f) +{ + int i; + int num_orbits; + int base_orbits; + int orbit_start; + build_img(f); + + f->center_of_universe.x = f->width / 2.0; + f->center_of_universe.y = f->height / 2.0; + f->center_of_universe.r = MAX(f->width, f->height) / 2.0; + + num_orbits = (f->percent_orbits * f->num_circles) / 100; + orbit_start = f->num_circles - num_orbits; + base_orbits = orbit_start + (num_orbits * f->base_orbits) / 100; + + free_circles(f); + + f->circles = (Circle*) calloc(f->num_circles, sizeof(Circle)); + if ( f->circles == NULL ) + { + fprintf(stderr, "%s: Failed to allocate off_img\n", + progname); + exit(1); + } + + for(i = 0; i < f->num_circles; ++i) + { + int j; + Circle *circle = f->circles + i; + + /* make this a pref */ + + if ( i >= orbit_start ) + circle->path_type = ORBIT; + else + circle->path_type = LINEAR; + + + if ( circle->path_type == LINEAR ) + { + circle->x = frand(f->width); + circle->y = frand(f->height); + + circle->dx = frand(0.5) - 0.25; + circle->dy = frand(0.5) - 0.25; + /* circle->dy = 0; */ + /* circle->r = f->height * (0.05 + frand(0.1)); */ + circle->radius = 5 + frand(55); + + /* in case we want orbits based on lines */ + circle->r = MIN(f->width, f->height) / 2.0; + circle->center = NULL; + } + else /* == ORBIT */ + { + if (i < base_orbits ) + { + if ( f->base_on_center ) + circle->center = &f->center_of_universe; + else + { + circle->center = f->circles + + ((int)frand(orbit_start - 0.1)); + } + + circle->r = 1 + frand(MIN(f->width, f->height) / 2.0); + + /* circle->radius = 5 + frand(55); */ + } + else + { + /* give a preference for the earlier circles */ + + double p = frand(0.9); + + circle->center = f->circles + (int) (p*i); + + circle->r = 1 + 0.5 * circle->center->r + 0.5 * frand(circle->center->r); + /* circle->r = 1 + frand(circle->center->r / 2); */ + + + /* circle->radius = MAX(5, frand(circle->r)); */ + /* circle->radius = 5 + frand(55); */ + } + + circle->radius = 5 + frand(MIN(55, circle->r)); + circle->dtheta = (frand(0.5) - 0.25) / circle->r; + circle->theta = frand(2 * M_PI); + + circle->x = circle->r * cos(circle->theta) + circle->center->x; + circle->y = circle->r * sin(circle->theta) + circle->center->y; + + } + + /* make this a command line option */ + circle->num_painters = 3; + circle->painters = (SandPainter*) calloc(circle->num_painters, + sizeof(SandPainter)); + if ( circle->painters == NULL ) + { + fprintf(stderr, "%s: failed to allocate painters", progname); + exit(1); + } + + for(j = 0; j < circle->num_painters; ++j) + { + SandPainter *painter = circle->painters + j; + + painter->gain = frand(0.09) + 0.01; + painter->p = frand(1.0); + painter->color = + f->parsedcolors[(int)(frand(0.999) * f->numcolors)]; + } + } +} + +static void moveCircles(struct field *f) +{ + int i; + + for(i = 0; i < f->num_circles; ++i) + { + Circle *circle = f->circles + i; + + if ( circle->path_type == LINEAR ) + { + circle->x += circle->dx; + circle->y += circle->dy; + +#if 0 + if ( circle->x < -circle->radius ) + circle->x = f->width + circle->radius; + else if ( circle->x >= f->width + circle->radius ) + circle->x = -circle->radius; + + if ( circle->y < -circle->radius ) + circle->y = f->height + circle->radius; + else if ( circle->y >= f->height + circle->radius ) + circle->y = -circle->radius; +#else + if ( circle->x < 0 ) circle->x += f->width; + else if ( circle->x >= f->width ) circle->x -= f->width; + + if ( circle->y < 0 ) circle->y += f->height; + else if ( circle->y >= f->height ) circle->y -= f->height; +#endif + } + else /* (circle->path_type == ORBIT) */ + { + circle->theta += circle->dtheta; + + if ( circle->theta < 0 ) circle->theta += 2 * M_PI; + else if ( circle->theta > 2 * M_PI ) circle->theta -= 2 * M_PI; + + circle->x = circle->r * cos(circle->theta) + circle->center->x; + circle->y = circle->r * sin(circle->theta) + circle->center->y; + +#if 0 + if ( circle->x < -circle->radius ) + circle->x += f->width + 2 * circle->radius; + else if ( circle->x >= f->width + circle->radius ) + circle->x -= f->width + 2 * circle->radius; + + if ( circle->y < -circle->radius ) + circle->y += f->height + 2 * circle->radius; + else if ( circle->y >= f->height + circle->radius ) + circle->y -= f->height + 2 * circle->radius; +#else + if ( circle->x < 0 ) circle->x += f->width; + else if ( circle->x >= f->width ) circle->x -= f->width; + + if ( circle->y < 0 ) circle->y += f->height; + else if ( circle->y >= f->height ) circle->y -= f->height; +#endif + } + } +} + +static void drawIntersections(Display *dpy, Window window, GC fgc, struct field *f) +{ + int i,j; + + /* One might be tempted to think 'hey, this is a crude algorithm + * that is going to check each of the n (n-1) / 2 possible + * intersections! Why not try bsp trees, quad trees, etc, etc, + * etc' + * + * In practice the time spent drawing the intersection of two + * circles dwarfs the time takes to check for intersection. + * Profiling on a 640x480 screen with 100 circles shows possible + * speed gains to be only a couple of percent. + * + * But hey, if you're bored, go have fun. Let me know how it + * turns out. + */ + + + for(i = 0; i < f->num_circles; ++i) + { + Circle *c1 = f->circles + i; + + if ( !f->draw_centers ) + { + /* the default branch */ + + for(j = i + 1; j < f->num_circles; ++j) + { + double d, dsqr, dx, dy; + Circle *c2 = f->circles + j; + +#ifdef TIME_ME + ++f->possible_intersections; +#endif + dx = c2->x - c1->x; + dy = c2->y - c1->y; + + dsqr = dx * dx + dy * dy; + d = sqrt(dsqr); + + if ( (fabs(dx) < (c1->radius + c2->radius)) && + (fabs(dy) < (c1->radius + c2->radius)) && + ( d < (c1->radius + c2->radius) ) && + ( d > fabs(c1->radius - c2->radius) ) ) + { + double d1, d2, r1sqr; + double bx, by; + double midpx, midpy; + double int1x, int1y; + double int2x, int2y; + int s; + + /* woo-hoo. the circles are neither outside nor + * inside each other. they intersect. + * + * Now, compute the coordinates of the points of + * intersection + */ + +#ifdef TIME_ME + ++f->intersection_count; +#endif + + /* unit vector in direction of c1 to c2 */ + bx = dx / d; + by = dy / d; + + r1sqr = c1->radius * c1->radius; + + /* distance from c1's center midpoint of intersection + * points */ + + d1 = 0.5 * (r1sqr - c2->radius * c2->radius + dsqr) / d; + + midpx = c1->x + d1 * bx; + midpy = c1->y + d1 * by; + + /* distance from midpoint to points of intersection */ + + d2 = sqrt(r1sqr - d1 * d1); + + int1x = midpx + d2 * by; + int1y = midpy - d2 * bx; + + int2x = midpx - d2 * by; + int2y = midpy + d2 * bx; + + for(s = 0; s < c1->num_painters; ++s) + { + paint(c1->painters + s, int1x, int1y, int2x, int2y, + dpy, window, fgc, f); + } + } + } + } + else /* f->draw_centers */ + { + XDrawPoint(dpy, window, fgc, c1->x, c1->y); + } + } +} + +struct state { + Display *dpy; + Window window; + + unsigned int max_cycles; + int growth_delay; + GC fgc; + XGCValues gcv; + XWindowAttributes xgwa; + + struct field *f; +}; + + +static void * +interaggregate_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + +#ifdef TIME_ME + int frames; + struct timeval tm1, tm2; + double tdiff; +#endif + + 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->num_circles = (get_integer_resource(st->dpy, "numCircles", "Integer")); + st->f->percent_orbits = (get_integer_resource(st->dpy, "percentOrbits", "Integer")); + st->f->base_orbits = (get_integer_resource(st->dpy, "baseOrbits", "Integer")); + st->f->base_on_center = (get_boolean_resource(st->dpy, "baseOnCenter", "Boolean")); + st->f->draw_centers = (get_boolean_resource(st->dpy, "drawCenters", "Boolean")); + + if (st->f->num_circles <= 1) + { + fprintf(stderr, "%s: Minimum number of circles is 2\n", + progname); + exit (1); + } + + if ( (st->f->percent_orbits < 0) || (st->f->percent_orbits > 100) ) + { + fprintf(stderr, "%s: percent-oribts must be between 0 and 100\n", + progname); + exit (1); + } + + if ( (st->f->base_orbits < 0) || (st->f->base_orbits > 100) ) + { + fprintf(stderr, "%s: base-oribts must be between 0 and 100\n", + progname); + exit (1); + } + + if ( st->f->percent_orbits == 100 ) + st->f->base_on_center = True; + + XGetWindowAttributes(st->dpy, st->window, &st->xgwa); + + build_colors(st->f, st->dpy, &st->xgwa); + + 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->height = st->xgwa.height; + st->f->width = st->xgwa.width; + st->f->visdepth = st->xgwa.depth; + st->f->fgcolor = st->gcv.foreground; + st->f->bgcolor = st->gcv.background; + + /* Initialize stuff */ + build_field(st->dpy, st->window, st->xgwa, st->fgc, st->f); + +#ifdef TIME_ME + gettimeofday(&tm1, NULL); + frames = 0; +#endif + + return st; +} + + +static unsigned long +interaggregate_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + 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_field(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); + } + } + + moveCircles(st->f); + drawIntersections(st->dpy, st->window, st->fgc, st->f); + + st->f->cycles++; + + + if (st->f->cycles >= st->max_cycles && st->max_cycles != 0) + { + build_field(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); + } + +#ifdef TIME_ME + frames++; + gettimeofday(&tm2, NULL); + + tdiff = (tm2.tv_sec - tm1.tv_sec) + + (tm2.tv_usec - tm1.tv_usec) * 0.00001; + + if ( tdiff > 1 ) + { + fprintf(stderr, "fps: %d %f %f\n", + frames, tdiff, frames / tdiff ); + + fprintf(stderr, "intersections: %d %d %f\n", + f->intersection_count, f->possible_intersections, + ((double)f->intersection_count) / + f->possible_intersections); + + fprintf(stderr, "fpi: %f\n", + ((double)frames) / f->intersection_count ); + + frames = 0; + tm1.tv_sec = tm2.tv_sec; + tm1.tv_usec = tm2.tv_usec; + + f->intersection_count = f->possible_intersections = 0; + } +#endif + + return st->growth_delay; +} + + +static void +interaggregate_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +interaggregate_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (screenhack_event_helper (dpy, window, event)) + { + st->f->height--; /* act like a resize */ + return True; + } + return False; +} + +static void +interaggregate_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +XSCREENSAVER_MODULE ("Interaggregate", interaggregate) -- cgit v1.2.3-55-g7522