X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fpenrose.c;h=6317cb645377eed7f595b2526a8737fa9e95368a;hb=78add6e627ee5f10e1fa6f3852602ea5066eee5a;hp=a15f0009e13ee34e62374063893995755dcf606c;hpb=ffd8c0873576a9e3065696a624dce6b766b77062;p=xscreensaver diff --git a/hacks/penrose.c b/hacks/penrose.c index a15f0009..6317cb64 100644 --- a/hacks/penrose.c +++ b/hacks/penrose.c @@ -83,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 release_penrose 0 +# define penrose_handle_event 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 @@ -115,13 +116,13 @@ static OptionStruct desc[] = {"-/+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 ModStruct penrose_description = -{"penrose", "init_penrose", "draw_penrose", "release_penrose", - "init_penrose", "init_penrose", (char *) NULL, &penrose_opts, +{"penrose", "init_penrose", "draw_penrose", (char *) NULL, + "init_penrose", "init_penrose", "free_penrose", &penrose_opts, 10000, 1, 1, -40, 64, 1.0, "", "Shows Penrose's quasiperiodic tilings", 0, NULL}; @@ -255,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]; @@ -321,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, line_width; + 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) @@ -354,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; @@ -374,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; @@ -385,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); @@ -401,9 +402,10 @@ fived_to_loc(int fived[], tiling_c * tp, XPoint *pt) /* Mop up dynamic data for one screen. */ -static void -free_penrose(tiling_c * tp) +ENTRYPOINT void +free_penrose(ModeInfo * mi) { + tiling_c * tp = &tilings[MI_SCREEN(mi)]; register fringe_node_c *fp1, *fp2; register forced_node_c *lp1, *lp2; @@ -426,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); tp = &tilings[MI_SCREEN(mi)]; #if 0 /* if you do this, then the -ammann and -no-ammann options don't work. @@ -460,6 +458,13 @@ init_penrose(ModeInfo * mi) MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi); } size = MI_SIZE(mi); + tp->line_width = 1; + + if (MI_WIDTH(mi) > 2560) { /* Retina displays */ + size *= 3; + tp->line_width *= 3; + } + if (size < -MINSIZE) tp->edge_length = NRAND(MIN(-size, MAX(MINSIZE, MIN(tp->width, tp->height) / 2)) - MINSIZE + 1) + MINSIZE; @@ -475,18 +480,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) { @@ -495,7 +500,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; @@ -504,7 +509,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) { @@ -513,7 +518,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; @@ -532,6 +537,8 @@ init_penrose(ModeInfo * mi) fp->fived[i] = 2 * NRAND(2) - 1; fived_to_loc(fp->fived, tp, &(fp->loc)); /* That's it! We have created our first edge. */ + + MI_CLEARWINDOW(mi); } /*- @@ -684,6 +691,8 @@ draw_tile(fringe_node_c * v1, fringe_node_c * v2, XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); XFillPolygon(display, window, gc, pts, 4, Convex, CoordModeOrigin); XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XSetLineAttributes(display, gc, tp->line_width, + LineSolid, CapNotLast, JoinMiter); XDrawLines(display, window, gc, pts, 5, CoordModeOrigin); if (tp->ammann) { @@ -691,12 +700,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)); @@ -705,10 +713,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 { @@ -961,9 +969,13 @@ alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp) fived_to_loc(v->fived, tp, &(v->loc)); if (v->loc.x < 0 || v->loc.y < 0 || v->loc.x >= tp->width || v->loc.y >= tp->height) { + int ww = tp->width; + int hh = tp->height; + if (ww < 200) ww = 200; /* tiny window */ + if (hh < 200) hh = 200; v->off_screen = True; - if (v->loc.x < -tp->width || v->loc.y < -tp->height - || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height) + if (v->loc.x < -ww || v->loc.y < -hh || + v->loc.x >= 2 * ww || v->loc.y >= 2 * hh) tp->done = True; } else { v->off_screen = False; @@ -1122,7 +1134,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; @@ -1251,12 +1263,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; @@ -1283,10 +1295,8 @@ draw_penrose(ModeInfo * mi) if (tp->fringe.nodes->prev == tp->fringe.nodes->next) { vertex_type_c vtype = (unsigned char) (VT_TOTAL_MASK & LRAND()); - MI_CLEARWINDOW(mi); - if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype)) - free_penrose(tp); + free_penrose(mi); return; } /* No visible nodes left. */ @@ -1329,18 +1339,14 @@ 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; - - for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) - free_penrose(&tilings[screen]); - (void) free((void *) tilings); - tilings = (tiling_c *) NULL; - } + tiling_c *tp = &tilings[MI_SCREEN(mi)]; + tp->width = width; + tp->height = height; } +XSCREENSAVER_MODULE ("Penrose", penrose) + #endif /* MODE_penrose */