X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fkaleidescope.c;h=c2b11ec1db552b91e7de457a3816d8993be5d620;hp=22f4a9b0319917d9f317883aa70dfe05fd5b69cf;hb=07faf451b99879183ed7e909e43a0e065be1ee7f;hpb=c6b273ef7292ba10943694df1656b05203d7b62f diff --git a/hacks/kaleidescope.c b/hacks/kaleidescope.c index 22f4a9b0..c2b11ec1 100644 --- a/hacks/kaleidescope.c +++ b/hacks/kaleidescope.c @@ -1,4 +1,4 @@ -/* kaleidescope, Copyright (c) 1997 Ron Tapia +/* kaleidescope, Copyright (c) 1997, 2006 Ron Tapia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -23,19 +23,36 @@ * */ - #include #include #include -#include -#include "spline.h" #include "screenhack.h" +#include "spline.h" + +#define NEWX(x,y) ((x*g->costheta) + (y*g->sintheta)) +#define NEWY(x,y) ((y*g->costheta) - (x*g->sintheta)) -#define NEWX(x,y) ((x*g.costheta) + (y*g.sintheta)) -#define NEWY(x,y) ((y*g.costheta) - (x*g.sintheta)) +typedef struct state GLOBAL; +typedef struct Obj OBJECT; +struct Obj { + int type; + int time; + void (*propigate) (GLOBAL *, OBJECT *); + void (*draw) (GLOBAL *, OBJECT *); + void (*init) (GLOBAL *, OBJECT *); + void *cur; +}; + +typedef struct KSEGMENT { + struct KSEGMENT *next; + XColor color; + int drawn; + short int x1,y1,x2,y2; /* these are in the natural coordinate system */ + XSegment *xsegments; /* these are in the X coordinate system */ +} Ksegment; -typedef struct { +struct state { int xoff, yoff; /* offset of origin xmax/2, ymax/2 */ int xmax, ymax; /* width, height of window */ float costheta, sintheta; @@ -56,39 +73,22 @@ typedef struct { unsigned long delay; unsigned short redmin,redrange,greenmin,greenrange,bluemin,bluerange; int color_mode; -} GLOBAL; -typedef struct Obj OBJECT; -struct Obj { - int type; - int time; - void (*propogate) (OBJECT *); - void (*draw) (OBJECT *); - void (*init) (OBJECT *); - void *cur; -}; - -typedef struct KSEGMENT { - struct KSEGMENT *next; - XColor color; - int drawn; - short int x1,y1,x2,y2; /* these are in the natural coordinate system */ - XSegment *xsegments; /* these are in the X coordinate system */ -} Ksegment; + OBJECT *objects; + int counter; -/* BEGIN global variables */ + int done_once; +}; -GLOBAL g; -OBJECT *objects; -char *progclass = "Kaleidescope"; -char *defaults [] = { - "*background: black", - "*foreground: white", +static const char *kaleidescope_defaults [] = { + ".background: black", + ".foreground: white", "*color_mode: nice", "*symmetry: 11", "*ntrails: 100", "*nsegments: 7", + "*narcs: 0", "*local_rotation: -59", "*global_rotation: 1", "*spring_constant: 5", @@ -102,7 +102,7 @@ char *defaults [] = { 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec kaleidescope_options [] = { { "-color_mode", ".color_mode", XrmoptionSepArg, 0 }, { "-symmetry", ".symmetry", XrmoptionSepArg, 0 }, { "-nsegments", ".nsegments", XrmoptionSepArg, 0 }, @@ -112,7 +112,7 @@ XrmOptionDescRec options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-spring_constant", ".spring_constant", XrmoptionSepArg, 0 }, { "-redmin", ".redmin", XrmoptionSepArg, 0 }, - { "-redrange", ".redmin", XrmoptionSepArg, 0 }, + { "-redrange", ".redrange", XrmoptionSepArg, 0 }, { "-bluemin", ".bluemin", XrmoptionSepArg, 0 }, { "-bluerange", ".bluerange", XrmoptionSepArg, 0 }, { "-greenmin", ".greenmin", XrmoptionSepArg, 0 }, @@ -123,23 +123,23 @@ XrmOptionDescRec options [] = { /* END global variables */ static void -krandom_color(XColor *color) +krandom_color(GLOBAL *g, XColor *color) { int r; r = random() % 3; - if((g.color_mode == 0) || (g.color_mode == 1)) { + if((g->color_mode == 0) || (g->color_mode == 1)) { - color->blue = ((r = random()) % g.bluerange) + g.bluemin; - color->green = ((r = random()) % g.greenrange) + g.greenmin; - color->red = ((r = random()) % g.redrange) + g.redmin; + color->blue = ((r = random()) % g->bluerange) + g->bluemin; + color->green = ((r = random()) % g->greenrange) + g->greenmin; + color->red = ((r = random()) % g->redrange) + g->redmin; - if(!XAllocColor(g.dpy, g.cmap, color)) { - color->pixel = g.default_fg_pixel; + if(!XAllocColor(g->dpy, g->cmap, color)) { + color->pixel = g->default_fg_pixel; } return; } else { - color->pixel = g.default_fg_pixel; + color->pixel = g->default_fg_pixel; return; } } @@ -155,14 +155,15 @@ kcopy_color(XColor *to, XColor *from) } static void -kcycle_color(XColor *color, +kcycle_color(GLOBAL *g, + XColor *color, unsigned short redstep, unsigned short greenstep, unsigned short bluestep) { unsigned short red,green,blue; - if (! g.color_mode) { + if (! g->color_mode) { XColor copy; color->flags = DoRed|DoGreen|DoBlue; color->red = (red = color->red) - redstep; @@ -170,9 +171,9 @@ kcycle_color(XColor *color, color->blue = (blue = color->blue) - bluestep; copy = *color; - if(!XAllocColor(g.dpy, g.cmap, color)) { + if(!XAllocColor(g->dpy, g->cmap, color)) { /* printf("couldn't alloc color...\n"); */ - color->pixel = g.default_fg_pixel; + color->pixel = g->default_fg_pixel; } copy.pixel = color->pixel; *color = copy; @@ -186,31 +187,31 @@ kcycle_color(XColor *color, static Ksegment * -create_ksegment (void) +create_ksegment (GLOBAL *g) { Ksegment *seg, *prev; XColor new_color; int i; unsigned short redstep,bluestep,greenstep; - krandom_color(&new_color); + krandom_color(g, &new_color); - redstep = new_color.red/(2 * g.ntrails); - greenstep = new_color.green/(2 * g.ntrails); - bluestep = new_color.blue/(2 * g.ntrails); + redstep = new_color.red/(2 * g->ntrails); + greenstep = new_color.green/(2 * g->ntrails); + bluestep = new_color.blue/(2 * g->ntrails); seg = (Ksegment *) malloc(sizeof(Ksegment)); - seg->xsegments = (XSegment *) malloc(g.symmetry * sizeof(XSegment)); + seg->xsegments = (XSegment *) malloc(g->symmetry * sizeof(XSegment)); prev = seg; - for(i=0; i< (g.ntrails - 1); i++) { + for(i=0; i< (g->ntrails - 1); i++) { - kcycle_color(&new_color,redstep,greenstep,bluestep); + kcycle_color(g, &new_color,redstep,greenstep,bluestep); kcopy_color(&(prev->color), &new_color); prev->next = (Ksegment*)malloc(sizeof(Ksegment)); - (prev->next)->xsegments = (XSegment*)malloc(g.symmetry * sizeof(XSegment)); + (prev->next)->xsegments = (XSegment*)malloc(g->symmetry * sizeof(XSegment)); prev->drawn = 0; prev = (prev->next); } @@ -223,26 +224,25 @@ create_ksegment (void) } static void -init_ksegment (OBJECT *obj) +init_ksegment (GLOBAL *g, OBJECT *obj) { /* Give the segment some random values */ - ((Ksegment *)obj->cur)->x1 = random() % g.xoff; - ((Ksegment *)obj->cur)->y1 = random() % g.yoff; - ((Ksegment *)obj->cur)->x2 = random() % g.xoff; - ((Ksegment *)obj->cur)->y2 = random() % g.yoff; + ((Ksegment *)obj->cur)->x1 = (g->xoff ? random() % g->xoff : 0); + ((Ksegment *)obj->cur)->y1 = (g->yoff ? random() % g->yoff : 0); + ((Ksegment *)obj->cur)->x2 = (g->xoff ? random() % g->xoff : 0); + ((Ksegment *)obj->cur)->y2 = (g->yoff ? random() % g->yoff : 0); } static void -draw_ksegment (OBJECT *obj) +draw_ksegment (GLOBAL *g, OBJECT *obj) { register short x1, y1, x2, y2; int dx, dy; int i; - static int counter=0; - counter++; + g->counter++; x1 = ((Ksegment *)obj->cur)->x1; /* in the natural coordinate system */ y1 = ((Ksegment *)obj->cur)->y1; @@ -254,47 +254,47 @@ draw_ksegment (OBJECT *obj) /* maybe throw away values and start over */ if( ((dx*dx) + (dy * dy)) < 100) { - init_ksegment (obj); + init_ksegment (g, obj); x1 = ((Ksegment *)obj->cur)->x1; /* in the natural coordinate system */ y1 = ((Ksegment *)obj->cur)->y1; x2 = ((Ksegment *)obj->cur)->x2; y2 = ((Ksegment *)obj->cur)->y2; } - for (i=0; isymmetry; i++) { (((Ksegment *)obj->cur)->xsegments)[i].x1 = NEWX(x1,y1); (((Ksegment *)obj->cur)->xsegments)[i].y1 = NEWY(x1,y1); (((Ksegment *)obj->cur)->xsegments)[i].x2 = NEWX(x2,y2); (((Ksegment *)obj->cur)->xsegments)[i].y2 = NEWY(x2,y2); - (((Ksegment *)obj->cur)->xsegments)[i].x1 = (x1 = (((Ksegment *)obj->cur)->xsegments)[i].x1) + g.xoff; - (((Ksegment *)obj->cur)->xsegments)[i].y1 = (y1 = (((Ksegment *)obj->cur)->xsegments)[i].y1) + g.yoff; - (((Ksegment *)obj->cur)->xsegments)[i].x2 = (x2 = (((Ksegment *)obj->cur)->xsegments)[i].x2) + g.xoff; - (((Ksegment *)obj->cur)->xsegments)[i].y2 = (y2 = (((Ksegment *)obj->cur)->xsegments)[i].y2) + g.yoff; + (((Ksegment *)obj->cur)->xsegments)[i].x1 = (x1 = (((Ksegment *)obj->cur)->xsegments)[i].x1) + g->xoff; + (((Ksegment *)obj->cur)->xsegments)[i].y1 = (y1 = (((Ksegment *)obj->cur)->xsegments)[i].y1) + g->yoff; + (((Ksegment *)obj->cur)->xsegments)[i].x2 = (x2 = (((Ksegment *)obj->cur)->xsegments)[i].x2) + g->xoff; + (((Ksegment *)obj->cur)->xsegments)[i].y2 = (y2 = (((Ksegment *)obj->cur)->xsegments)[i].y2) + g->yoff; } - XSetForeground(g.dpy, g.draw_gc, (((Ksegment *)obj->cur)->color).pixel); + XSetForeground(g->dpy, g->draw_gc, (((Ksegment *)obj->cur)->color).pixel); - XDrawSegments(g.dpy, g.window, g.draw_gc, ((Ksegment *)obj->cur)->xsegments, g.symmetry); + XDrawSegments(g->dpy, g->window, g->draw_gc, ((Ksegment *)obj->cur)->xsegments, g->symmetry); ((Ksegment *)obj->cur)->drawn = 1; if (((((Ksegment *)obj->cur)->next)->drawn) != 0) { - XDrawSegments(g.dpy, g.window, g.erase_gc, ((Ksegment *)obj->cur)->next->xsegments, g.symmetry); + XDrawSegments(g->dpy, g->window, g->erase_gc, ((Ksegment *)obj->cur)->next->xsegments, g->symmetry); } } static void -propogate_ksegment(OBJECT *obj) +propigate_ksegment(GLOBAL *g, OBJECT *obj) { int t; short int x1,y1,x2,y2; short int midx,midy,nmidx,nmidy; float lsin, lcos, gsin, gcos; - lsin = sin((2*M_PI/10000)*g.local_rotation); - lcos = cos((2*M_PI/10000)*g.local_rotation); - gsin = sin((2*M_PI/10000)*g.global_rotation); - gcos = cos((2*M_PI/10000)*g.global_rotation); + lsin = sin((2*M_PI/10000)*g->local_rotation); + lcos = cos((2*M_PI/10000)*g->local_rotation); + gsin = sin((2*M_PI/10000)*g->global_rotation); + gcos = cos((2*M_PI/10000)*g->global_rotation); t=obj->time; obj->time = t + 1; @@ -328,28 +328,28 @@ propogate_ksegment(OBJECT *obj) } static void -init_objects (void) +init_objects (GLOBAL *g) { int i; - for (i=0; inobjects; i++) { + (g->objects[i].init)(g, g->objects + i); } } static void -create_objects (void) +create_objects (GLOBAL *g) { int i; - objects = (OBJECT *) malloc(g.nobjects * sizeof(OBJECT)); + g->objects = (OBJECT *) malloc(g->nobjects * sizeof(OBJECT)); - for (i=0; i< g.nsegments; i++) { - objects[i].cur = create_ksegment(); - objects[i].type = 1; - objects[i].time = 0; - objects[i].propogate = propogate_ksegment; - objects[i].draw = draw_ksegment; - objects[i].init = init_ksegment; + for (i=0; i< g->nsegments; i++) { + g->objects[i].cur = create_ksegment(g); + g->objects[i].type = 1; + g->objects[i].time = 0; + g->objects[i].propigate = propigate_ksegment; + g->objects[i].draw = draw_ksegment; + g->objects[i].init = init_ksegment; } /* Here we can add creation functions for other object types. */ @@ -357,97 +357,133 @@ create_objects (void) static void -propogate_objects (void) +propigate_objects (GLOBAL *g) { int i; - for(i=0; inobjects; i++) { + g->objects[i].propigate(g, g->objects + i); } } static void -draw_objects (void) +draw_objects (GLOBAL *g) { int i; - for(i=0; inobjects; i++) { + g->objects[i].draw(g, g->objects + i); } } static void -init_g (Display *dpy, Window window) +init_g (GLOBAL *g) { XWindowAttributes xgwa; XGCValues gcv; char *color_mode_str; - g.dpy = dpy; - g.window = window; + g->symmetry = get_integer_resource(g->dpy, "symmetry", "Integer"); + g->ntrails = get_integer_resource(g->dpy, "ntrails" , "Integer"); + g->nsegments = get_integer_resource(g->dpy, "nsegments", "Integer"); + g->narcs = get_integer_resource(g->dpy, "narcs", "Integer"); + g->local_rotation = get_integer_resource(g->dpy, "local_rotation", "Integer"); + g->global_rotation = get_integer_resource(g->dpy, "global_rotation", "Integer"); + g->spring_constant = get_integer_resource(g->dpy, "spring_constant", "Integer"); + g->delay = get_integer_resource(g->dpy, "delay", "Integer"); + g->nobjects = g->nsegments + g->narcs; - g.symmetry = get_integer_resource("symmetry", "Integer"); - g.ntrails = get_integer_resource("ntrails" , "Integer"); - g.nsegments = get_integer_resource("nsegments", "Integer"); - g.narcs = get_integer_resource("narcs", "Integer"); - g.local_rotation = get_integer_resource("local_rotation", "Integer"); - g.global_rotation = get_integer_resource("global_rotation", "Integer"); - g.spring_constant = get_integer_resource("sprint_constatnt", "Integer"); - g.delay = get_integer_resource("delay", "Integer"); - g.nobjects = g.nsegments + g.narcs; - - color_mode_str = get_string_resource("color_mode", "color_mode"); + color_mode_str = get_string_resource(g->dpy, "color_mode", "color_mode"); /* make into an enum... */ if(!color_mode_str) { - g.color_mode = 0; + g->color_mode = 0; } else if (!strcmp(color_mode_str, "greedy")) { - g.color_mode = 0; + g->color_mode = 0; } else if (!strcmp(color_mode_str, "nice")) { - g.color_mode = 1; + g->color_mode = 1; } else { - g.color_mode = 2; + g->color_mode = 2; } - XGetWindowAttributes (dpy, (Drawable) window, &xgwa); - g.xmax = xgwa.width; - g.ymax = xgwa.height; - g.xoff = g.xmax/2; - g.yoff = g.ymax/2; - g.costheta = cos(2*M_PI/g.symmetry); - g.sintheta = sin(2*M_PI/g.symmetry); - g.cmap = xgwa.colormap; - - g.redmin = get_integer_resource("redmin", "Integer"); - g.redrange = get_integer_resource("redrange", "Integer"); - g.greenmin = get_integer_resource("greenmin", "Integer"); - g.greenrange = get_integer_resource("greenrange", "Integer"); - g.bluemin = get_integer_resource("bluemin", "Integer"); - g.bluerange = get_integer_resource("bluerange", "Integer"); + XGetWindowAttributes (g->dpy, g->window, &xgwa); + g->xmax = xgwa.width; + g->ymax = xgwa.height; + g->xoff = g->xmax/2; + g->yoff = g->ymax/2; + g->costheta = cos(2*M_PI/g->symmetry); + g->sintheta = sin(2*M_PI/g->symmetry); + g->cmap = xgwa.colormap; + + g->redmin = get_integer_resource(g->dpy, "redmin", "Integer"); + g->redrange = get_integer_resource(g->dpy, "redrange", "Integer"); + g->greenmin = get_integer_resource(g->dpy, "greenmin", "Integer"); + g->greenrange = get_integer_resource(g->dpy, "greenrange", "Integer"); + g->bluemin = get_integer_resource(g->dpy, "bluemin", "Integer"); + g->bluerange = get_integer_resource(g->dpy, "bluerange", "Integer"); gcv.line_width = 1; gcv.cap_style = CapRound; - gcv.foreground = g.default_fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, g.cmap); - g.draw_gc = XCreateGC (dpy, (Drawable) window, GCForeground|GCLineWidth|GCCapStyle, &gcv); + gcv.foreground = g->default_fg_pixel = get_pixel_resource (g->dpy, g->cmap, "foreground", "Foreground"); + g->draw_gc = XCreateGC (g->dpy, g->window, GCForeground|GCLineWidth|GCCapStyle, &gcv); + + gcv.foreground = get_pixel_resource (g->dpy, g->cmap, "background", "Background"); + g->erase_gc = XCreateGC (g->dpy, g->window, GCForeground|GCLineWidth|GCCapStyle,&gcv); + +# ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (g->dpy, g->draw_gc, False); + jwxyz_XSetAntiAliasing (g->dpy, g->erase_gc, False); +# endif + + +} - gcv.foreground = get_pixel_resource ("background", "Background", g.dpy, g.cmap); - g.erase_gc = XCreateGC (dpy, (Drawable) window, GCForeground|GCLineWidth|GCCapStyle,&gcv); +static void * +kaleidescope_init (Display *dpy, Window window) +{ + GLOBAL *g = (GLOBAL *) calloc (1, sizeof(*g)); + g->dpy = dpy; + g->window = window; + init_g (g); + create_objects(g); + init_objects (g); + return g; } -void -screenhack (Display *dpy, Window window) +static unsigned long +kaleidescope_draw (Display *dpy, Window window, void *closure) { - init_g (dpy, window); - create_objects(); - init_objects (); - - while (1) - { - draw_objects (); - XSync (dpy, True); - if(g.delay) { - screenhack_usleep(g.delay); - } - propogate_objects(); - } + GLOBAL *g = (GLOBAL *) closure; + if (g->done_once) + propigate_objects(g); + else + g->done_once = 1; + draw_objects (g); + return g->delay; } + +static void +kaleidescope_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + GLOBAL *g = (GLOBAL *) closure; + g->xmax = w; + g->ymax = h; + g->xoff = g->xmax/2; + g->yoff = g->ymax/2; +} + +static Bool +kaleidescope_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +kaleidescope_free (Display *dpy, Window window, void *closure) +{ + GLOBAL *g = (GLOBAL *) closure; + free (g); +} + +XSCREENSAVER_MODULE ("Kaleidescope", kaleidescope)