From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / penrose.c
index aa62ab03634250dda84b08e3712a6e2cb0956ea8..0836ee7326792f2202059e10bddeeed6fda8585e 100644 (file)
@@ -18,9 +18,8 @@
                                 http://www.nine.org/notw/notw.html
  */
 
-#if !defined( lint ) && !defined( SABER )
+#if 0
 static const char sccsid[] = "@(#)penrose.c    5.00 2000/11/01 xlockmore";
-
 #endif
 
 /*-
@@ -84,16 +83,17 @@ If one of these are hit penrose will reinitialize.
 
 #ifdef STANDALONE
 #define MODE_penrose
-#define PROGCLASS "Penrose"
-#define HACK_INIT init_penrose
-#define HACK_DRAW draw_penrose
-#define penrose_opts xlockmore_opts
-#define DEFAULTS "*delay: 10000 \n" \
- "*size: 40 \n" \
- "*ncolors: 64 \n"
-#include "xlockmore.h"         /* from the xscreensaver distribution */
+#define DEFAULTS       "*delay: 10000 \n" \
+                                       "*size: 40 \n" \
+                                       "*ncolors: 64 \n" \
+                                       "*fpsSolid: true \n" \
+                                       "*ignoreRotation: True \n" \
+
+# define refresh_penrose 0
+# define release_penrose 0
+# include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
-#include "xlock.h"             /* from the xlockmore distribution */
+# include "xlock.h"            /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef MODE_penrose
@@ -104,19 +104,19 @@ static Bool ammann;
 
 static XrmOptionDescRec opts[] =
 {
-       {(char *) "-ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "on"},
-       {(char *) "+ammann", (char *) ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"}
+       {"-ammann", ".penrose.ammann", XrmoptionNoArg, "on"},
+       {"+ammann", ".penrose.ammann", XrmoptionNoArg, "off"}
 };
 static argtype vars[] =
 {
-       {(caddr_t *) & ammann, (char *) "ammann", (char *) "Ammann", (char *) DEF_AMMANN, t_Bool}
+       {&ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool}
 };
 static OptionStruct desc[] =
 {
-       {(char *) "-/+ammann", (char *) "turn on/off Ammann lines"}
+       {"-/+ammann", "turn on/off Ammann lines"}
 };
 
-ModeSpecOpt penrose_opts =
+ENTRYPOINT ModeSpecOpt penrose_opts =
 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
 
 #ifdef USE_MODULES
@@ -256,21 +256,6 @@ typedef struct {
 } forced_pool_c;
 
 
-/* This is the data related to the tiling of one screen. */
-typedef struct {
-       int         width, height;
-       XPoint      origin;
-       int         edge_length;
-       fringe_c    fringe;
-       forced_pool_c forced;
-       int         done, failures;
-       unsigned long thick_color, thin_color;
-       int         busyLoop;
-       Bool        ammann;
-} tiling_c;
-
-static tiling_c *tilings = (tiling_c *) NULL;
-
 /* The tiles are listed in counterclockwise order. */
 typedef struct {
        vertex_type_c tiles[MAX_TILES_PER_VERTEX];
@@ -322,6 +307,25 @@ static angle_c vtype_angles[] =
 #define vtype_angle( v) (vtype_angles[ v])
 
 
+/* This is the data related to the tiling of one screen. */
+typedef struct {
+       int         width, height;
+       XPoint      origin;
+       int         edge_length;
+       fringe_c    fringe;
+       forced_pool_c forced;
+       int         done, failures;
+       unsigned long thick_color, thin_color;
+       int         busyLoop;
+       Bool        ammann;
+    float       ammann_r;
+    fcoord_c    fived_table[5];
+} tiling_c;
+
+static tiling_c *tilings = (tiling_c *) NULL;
+
+
+
 /* Direction angle of an edge. */
 static      angle_c
 vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side)
@@ -355,8 +359,7 @@ vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side)
 static void
 add_unit_vec(angle_c dir, int *fived)
 {
-       static int  dir2i[] =
-       {0, 3, 1, 4, 2};
+       static const int dir2i[] = {0, 3, 1, 4, 2};
 
        while (dir < 0)
                dir += 10;
@@ -375,9 +378,6 @@ add_unit_vec(angle_c dir, int *fived)
 static void
 fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
 {
-       static fcoord_c fived_table[5] =
-       {
-               {.0, .0}};
        float       fifth = 8 * atan(1.) / 5;
        register int i;
        register float r;
@@ -386,15 +386,15 @@ fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
        *pt = tp->origin;
        offset.x = 0.0;
        offset.y = 0.0;
-       if (fived_table[0].x == .0)
+       if (tp->fived_table[0].x == .0)
                for (i = 0; i < 5; i++) {
-                       fived_table[i].x = cos(fifth * i);
-                       fived_table[i].y = sin(fifth * i);
+                       tp->fived_table[i].x = cos(fifth * i);
+                       tp->fived_table[i].y = sin(fifth * i);
                }
        for (i = 0; i < 5; i++) {
                r = fived[i] * tp->edge_length;
-               offset.x += r * fived_table[i].x;
-               offset.y -= r * fived_table[i].y;
+               offset.x += r * tp->fived_table[i].x;
+               offset.y -= r * tp->fived_table[i].y;
        }
        (*pt).x += (int) (offset.x + .5);
        (*pt).y += (int) (offset.y + .5);
@@ -403,8 +403,9 @@ fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
 
 /* Mop up dynamic data for one screen. */
 static void
-free_penrose(tiling_c * tp)
+free_penrose(ModeInfo * mi)
 {
+       tiling_c * tp = &tilings[MI_SCREEN(mi)];
        register fringe_node_c *fp1, *fp2;
        register forced_node_c *lp1, *lp2;
 
@@ -427,18 +428,14 @@ free_penrose(tiling_c * tp)
 
 
 /* Called to init the mode. */
-void
+ENTRYPOINT void
 init_penrose(ModeInfo * mi)
 {
        tiling_c   *tp;
        fringe_node_c *fp;
        int         i, size;
 
-       if (tilings == NULL) {
-               if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi),
-                                                sizeof (tiling_c))) == NULL)
-                       return;
-       }
+       MI_INIT (mi, tilings, free_penrose);
        tp = &tilings[MI_SCREEN(mi)];
 
 #if 0 /* if you do this, then the -ammann and -no-ammann options don't work.
@@ -476,18 +473,18 @@ init_penrose(ModeInfo * mi)
        tp->origin.y = (tp->height / 2 + NRAND(tp->height)) / 2;
        tp->fringe.n_nodes = 2;
        if (tp->fringe.nodes != NULL)
-               free_penrose(tp);
+               free_penrose(mi);
        if (tp->fringe.nodes != NULL || tp->forced.first != 0) {
                if (MI_IS_VERBOSE(mi)) {
                        (void) fprintf(stderr, "Weirdness in init_penrose()\n");
                        (void) fprintf(stderr, "tp->fringe.nodes = NULL && tp->forced.first = 0\n");
                }
-               free_penrose(tp);       /* Try again */
+               free_penrose(mi);       /* Try again */
                tp->done = True;
        }
        tp->forced.n_nodes = tp->forced.n_visible = 0;
        if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
-               free_penrose(tp);
+               free_penrose(mi);
                return;
        }
        if (fp == 0) {
@@ -496,7 +493,7 @@ init_penrose(ModeInfo * mi)
                        (void) fprintf(stderr, "fp = 0\n");
                }
                if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) {
-                       free_penrose(tp);
+                       free_penrose(mi);
                        return;
                }
                tp->done = True;
@@ -505,7 +502,7 @@ init_penrose(ModeInfo * mi)
        fp->rule_mask = (1 << N_VERTEX_RULES) - 1;
        fp->list_ptr = 0;
        if  ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
-               free_penrose(tp);
+               free_penrose(mi);
                return;
        }
        if (fp->next == 0) {
@@ -514,7 +511,7 @@ init_penrose(ModeInfo * mi)
                        (void) fprintf(stderr, "fp->next = 0\n");
                }
                if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) {
-                       free_penrose(tp);
+                       free_penrose(mi);
                        return;
                }
                tp->done = True;
@@ -692,12 +689,11 @@ draw_tile(fringe_node_c * v1, fringe_node_c * v2,
                   fail miserably on a b&w display. */
 
                if ((vtype & VT_TYPE_MASK) == VT_THICK) {
-                       static float r = .0;
 
-                       if (r == .0) {
+                       if (tp->ammann_r == .0) {
                                float       pi10 = 2 * atan(1.) / 5;
 
-                               r = 1 - sin(pi10) / (2 * sin(3 * pi10));
+                               tp->ammann_r = 1 - sin(pi10) / (2 * sin(3 * pi10));
                        }
                        if (MI_NPIXELS(mi) > 2)
                                XSetForeground(display, gc, MI_PIXEL(mi, tp->thin_color));
@@ -706,10 +702,10 @@ draw_tile(fringe_node_c * v1, fringe_node_c * v2,
                                XSetLineAttributes(display, gc, 1, LineOnOffDash, CapNotLast, JoinMiter);
                        }
                        XDrawLine(display, window, gc,
-                             (int) (r * pts[3].x + (1 - r) * pts[0].x + .5),
-                             (int) (r * pts[3].y + (1 - r) * pts[0].y + .5),
-                             (int) (r * pts[1].x + (1 - r) * pts[0].x + .5),
-                            (int) (r * pts[1].y + (1 - r) * pts[0].y + .5));
+                             (int) (tp->ammann_r * pts[3].x + (1 - tp->ammann_r) * pts[0].x + .5),
+                             (int) (tp->ammann_r * pts[3].y + (1 - tp->ammann_r) * pts[0].y + .5),
+                             (int) (tp->ammann_r * pts[1].x + (1 - tp->ammann_r) * pts[0].x + .5),
+                            (int) (tp->ammann_r * pts[1].y + (1 - tp->ammann_r) * pts[0].y + .5));
                        if (MI_NPIXELS(mi) <= 2)
                                XSetLineAttributes(display, gc, 1, LineSolid, CapNotLast, JoinMiter);
                } else {
@@ -1123,7 +1119,7 @@ add_forced_tile(ModeInfo * mi, forced_node_c * node)
 {
        tiling_c   *tp = &tilings[MI_SCREEN(mi)];
        unsigned    side;
-       vertex_type_c vtype;
+       vertex_type_c vtype = 0;
        rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
        int         n;
 
@@ -1252,12 +1248,12 @@ add_random_tile(fringe_node_c * vertex, ModeInfo * mi)
                if (MI_IS_VERBOSE(mi)) {
                        (void) fprintf(stderr, "Weirdness in add_random_tile()\n");
                }
-               free_penrose(tp);
+               free_penrose(mi);
        }
 }
 
 /* One step of the growth algorithm. */
-void
+ENTRYPOINT void
 draw_penrose(ModeInfo * mi)
 {
        int         i = 0, n;
@@ -1287,7 +1283,7 @@ draw_penrose(ModeInfo * mi)
                MI_CLEARWINDOW(mi);
 
                if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype))
-                       free_penrose(tp);
+                       free_penrose(mi);
                return;
        }
        /* No visible nodes left. */
@@ -1330,18 +1326,26 @@ draw_penrose(ModeInfo * mi)
 }
 
 
-/* Total clean-up. */
-void
-release_penrose(ModeInfo * mi)
+ENTRYPOINT void
+reshape_penrose(ModeInfo * mi, int width, int height)
 {
-       if (tilings != NULL) {
-               int         screen;
+       tiling_c   *tp = &tilings[MI_SCREEN(mi)];
+       tp->width = width;
+       tp->height = height;
+}
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_penrose(&tilings[screen]);
-               (void) free((void *) tilings);
-               tilings = (tiling_c *) NULL;
-       }
+ENTRYPOINT Bool
+penrose_handle_event (ModeInfo *mi, XEvent *event)
+{
+  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+    {
+      init_penrose (mi);
+      return True;
+    }
+  return False;
 }
 
+
+XSCREENSAVER_MODULE ("Penrose", penrose)
+
 #endif /* MODE_penrose */