#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
{"-/+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};
} 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];
#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)
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;
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;
*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);
/* 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;
/* 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.
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;
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) {
(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;
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) {
(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;
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);
}
/*-
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) {
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));
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 {
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;
{
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;
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;
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. */
}
-/* 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 */