http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / kaleidescope.c
index 6e66fdd837a0e08c6de6959b505e7611dac25a24..8c727317e19a63b369e97ae8e74ea6330fd6045e 100644 (file)
@@ -1,4 +1,4 @@
-/* kaleidescope, Copyright (c) 1997 Ron Tapia <tapia@nmia.com>
+/* kaleidescope, Copyright (c) 1997, 2006 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
  *
  */
 
-
 #include <stdio.h>
 #include <math.h>
 #include <time.h>
-#include <X11/Xlib.h>
-#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 [] = {
+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 = 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)
+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; i<g.symmetry; i++) {
+  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;
+    (((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; i<g.nobjects; i++) {
-    (objects[i].init)(objects + i);
+  for (i=0; i<g->nobjects; 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,98 +357,133 @@ create_objects (void)
 
 
 static void
-propogate_objects (void)
+propigate_objects (GLOBAL *g)
 {
   int i;
 
-  for(i=0; i<g.nobjects; i++) {
-    objects[i].propogate(objects + i);
+  for(i=0; i<g->nobjects; i++) {
+    g->objects[i].propigate(g, g->objects + i);
   }
 }
 
 static void
-draw_objects (void)
+draw_objects (GLOBAL *g)
 {
   int i;
 
-  for(i=0; i<g.nobjects; i++) {
-    objects[i].draw(objects + i);
+  for(i=0; i<g->nobjects; 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, False);
-     if(g.delay) {
-       screenhack_handle_events (dpy);
-       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)