+++ /dev/null
-/* kaleidescope, Copyright (c) 1997 Ron Tapia <tapia@nmia.com>
- *
- * 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.
- */
-
-/*
- * The above, for lack of a better copyright statement in easy reach
- * was just lifted from the xscreensaver source.
- *
- * One of the odd things about this hack is that the radial motion of the
- * segments depends on roundoff error alone.
- *
- * I tried to make the source easy to add other shapes. So far, I've
- * only messed with elipses and I couldn't do much with them that looked
- * cool. A nice addition would be to add some sort of spline based shapes.
- * Maybe rectangles would look nice.
- *
- */
-
-
-#include <stdio.h>
-#include <math.h>
-#include <time.h>
-#include <X11/Xlib.h>
-#include "spline.h"
-#include "screenhack.h"
-
-#define NEWX(x,y) ((x*g.costheta) + (y*g.sintheta))
-#define NEWY(x,y) ((y*g.costheta) - (x*g.sintheta))
-
-
-typedef struct {
- int xoff, yoff; /* offset of origin xmax/2, ymax/2 */
- int xmax, ymax; /* width, height of window */
- float costheta, sintheta;
- int symmetry;
- int ntrails;
- int nsegments;
- int narcs;
- int nobjects;
- int local_rotation;
- int global_rotation;
- int spring_constant;
- Colormap cmap;
- GC draw_gc;
- GC erase_gc;
- unsigned int default_fg_pixel;
- Display *dpy;
- Window window;
- 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;
-
-/* BEGIN global variables */
-
-GLOBAL g;
-OBJECT *objects;
-
-char *progclass = "Kaleidescope";
-char *defaults [] = {
- ".background: black",
- ".foreground: white",
- "*color_mode: nice",
- "*symmetry: 11",
- "*ntrails: 100",
- "*nsegments: 7",
- "*local_rotation: -59",
- "*global_rotation: 1",
- "*spring_constant: 5",
- "*delay: 20000",
- "*redmin: 30000",
- "*redrange: 20000",
- "*greenmin: 30000",
- "*greenrange: 20000",
- "*bluemin: 30000",
- "*bluerange: 20000",
- 0
-};
-
-XrmOptionDescRec options [] = {
- { "-color_mode", ".color_mode", XrmoptionSepArg, 0 },
- { "-symmetry", ".symmetry", XrmoptionSepArg, 0 },
- { "-nsegments", ".nsegments", XrmoptionSepArg, 0 },
- { "-ntrails", ".ntrails", XrmoptionSepArg, 0 },
- { "-local_rotation", ".local_rotation", XrmoptionSepArg, 0 },
- { "-global_rotation", ".global_rotation", XrmoptionSepArg, 0 },
- { "-delay", ".delay", XrmoptionSepArg, 0 },
- { "-spring_constant", ".spring_constant", XrmoptionSepArg, 0 },
- { "-redmin", ".redmin", XrmoptionSepArg, 0 },
- { "-redrange", ".redmin", XrmoptionSepArg, 0 },
- { "-bluemin", ".bluemin", XrmoptionSepArg, 0 },
- { "-bluerange", ".bluerange", XrmoptionSepArg, 0 },
- { "-greenmin", ".greenmin", XrmoptionSepArg, 0 },
- { "-greenrange", ".greenrange", XrmoptionSepArg, 0 },
- { 0, 0, 0, 0 }
-};
-
-/* END global variables */
-
-static void
-krandom_color(XColor *color)
-{
- int r;
- r = random() % 3;
-
- 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;
-
- if(!XAllocColor(g.dpy, g.cmap, color)) {
- color->pixel = g.default_fg_pixel;
- }
- return;
- } else {
- color->pixel = g.default_fg_pixel;
- return;
- }
-}
-
-
-static void
-kcopy_color(XColor *to, XColor *from)
-{
- to->red = from->red;
- to->green = from->green;
- to->blue = from->blue;
- to->pixel = from->pixel;
-}
-
-static void
-kcycle_color(XColor *color,
- unsigned short redstep,
- unsigned short greenstep,
- unsigned short bluestep)
-{
- unsigned short red,green,blue;
-
- if (! g.color_mode) {
- XColor copy;
- color->flags = DoRed|DoGreen|DoBlue;
- color->red = (red = color->red) - redstep;
- color->green = (green = color->green) - greenstep;
- color->blue = (blue = color->blue) - bluestep;
- copy = *color;
-
- if(!XAllocColor(g.dpy, g.cmap, color)) {
- /* printf("couldn't alloc color...\n"); */
- color->pixel = g.default_fg_pixel;
- }
- copy.pixel = color->pixel;
- *color = copy;
-
- color->red = red - redstep;
- color->green = green- greenstep;
- color->blue = blue - bluestep;
- return;
- }
-}
-
-
-static Ksegment *
-create_ksegment (void)
-{
- Ksegment *seg, *prev;
- XColor new_color;
- int i;
- unsigned short redstep,bluestep,greenstep;
-
- krandom_color(&new_color);
-
- 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));
-
- prev = seg;
- for(i=0; i< (g.ntrails - 1); i++) {
-
- kcycle_color(&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->drawn = 0;
- prev = (prev->next);
- }
-
- prev->drawn = 0;
- prev->next = seg;
- kcopy_color(&(prev->color), &new_color);
-
- return seg;
-}
-
-static void
-init_ksegment (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;
-}
-
-
-static void
-draw_ksegment (OBJECT *obj)
-{
- register short x1, y1, x2, y2;
- int dx, dy;
- int i;
- static int counter=0;
-
- counter++;
-
- 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;
-
- dx = x2 - x1;
- dy = y2 - y1;
-
- /* maybe throw away values and start over */
- if( ((dx*dx) + (dy * dy)) < 100) {
- init_ksegment (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; i<g.symmetry; 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;
- }
-
- 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);
- ((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);
- }
-}
-
-static void
-propogate_ksegment(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);
-
- t=obj->time;
- obj->time = t + 1;
-
- x1 = ((Ksegment *) obj->cur)->x1;
- y1 = ((Ksegment *) obj->cur)->y1;
- x2 = ((Ksegment *) obj->cur)->x2;
- y2 = ((Ksegment *) obj->cur)->y2;
-
- midx = (x1 + x2)/2;
- midy = (y1 + y2)/2;
-
- nmidx = midx*gcos + midy*gsin;
- nmidy = midy*gcos - midx*gsin;
-
- x1 = x1 - midx;
- x2 = x2 - midx;
- y1 = y1 - midy;
- y2 = y2 - midy;
-
-
- /* This is where we move to the next ksegment... */
- obj->cur = ((Ksegment *)obj->cur)->next;
-
- ((Ksegment *)obj->cur)->x1 = ((x1*lcos) + (y1*lsin)) + nmidx;
- ((Ksegment *)obj->cur)->y1 = ((y1*lcos) - (x1*lsin)) + nmidy;
- ((Ksegment *)obj->cur)->x2 = ((x2*lcos) + (y2*lsin)) + nmidx;
- ((Ksegment *)obj->cur)->y2 = ((y2*lcos) - (x2*lsin)) + nmidy;
-
- return ;
-}
-
-static void
-init_objects (void)
-{
- int i;
- for (i=0; i<g.nobjects; i++) {
- (objects[i].init)(objects + i);
- }
-}
-
-static void
-create_objects (void)
-{
- int i;
-
- 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;
- }
-
- /* Here we can add creation functions for other object types. */
-}
-
-
-static void
-propogate_objects (void)
-{
- int i;
-
- for(i=0; i<g.nobjects; i++) {
- objects[i].propogate(objects + i);
- }
-}
-
-static void
-draw_objects (void)
-{
- int i;
-
- for(i=0; i<g.nobjects; i++) {
- objects[i].draw(objects + i);
- }
-}
-
-static void
-init_g (Display *dpy, Window window)
-{
- XWindowAttributes xgwa;
- XGCValues gcv;
- char *color_mode_str;
-
- g.dpy = dpy;
- g.window = window;
-
- 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");
-
- /* make into an enum... */
- if(!color_mode_str) {
- g.color_mode = 0;
- } else if (!strcmp(color_mode_str, "greedy")) {
- g.color_mode = 0;
- } else if (!strcmp(color_mode_str, "nice")) {
- g.color_mode = 1;
- } else {
- 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");
-
- 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 = get_pixel_resource ("background", "Background", g.dpy, g.cmap);
- g.erase_gc = XCreateGC (dpy, (Drawable) window, GCForeground|GCLineWidth|GCCapStyle,&gcv);
-}
-
-void
-screenhack (Display *dpy, Window window)
-{
- init_g (dpy, window);
- create_objects();
- init_objects ();
-
- while (1)
- {
- draw_objects ();
- XSync (dpy, False);
- if(g.delay) {
- screenhack_handle_events (dpy);
- usleep(g.delay);
- }
- propogate_objects();
- }
-}