ref: 827051dafea79f112e929c9cc7732183696fad72
parent: 828c7da78561768a52a2c38d7c8c9bc1d14c3120
author: Simon Tatham <anakin@pobox.com>
date: Tue Mar 28 16:35:03 EDT 2023
hat-test: alternative data output mode to write Python. This mode emits a sequence of calls to an imaginary Python function. Should be useful to anyone wanting to post-process the tiling in any way.
--- a/hat.c
+++ b/hat.c
@@ -1256,29 +1256,16 @@
bbox->started = true;
}
-static void header(psbbox *bbox)
-{
- float xext = bbox->tr.x - bbox->bl.x, yext = bbox->tr.y - bbox->bl.y;
- float ext = (xext > yext ? xext : yext);
- float scale = 500 / ext;
- float ox = 287 - scale * (bbox->bl.x + bbox->tr.x) / 2;
- float oy = 421 - scale * (bbox->bl.y + bbox->tr.y) / 2;
+typedef enum OutFmt { OF_POSTSCRIPT, OF_PYTHON } OutFmt;
- printf("%%!PS-Adobe-2.0\n%%%%Creator: hat-test from Simon Tatham's "
- "Portable Puzzle Collection\n%%%%Pages: 1\n"
- "%%%%BoundingBox: %f %f %f %f\n"
- "%%%%EndComments\n%%%%Page: 1 1\n",
- ox + scale * bbox->bl.x - 20, oy + scale * bbox->bl.y - 20,
- ox + scale * bbox->tr.x + 20, oy + scale * bbox->tr.y + 20);
+typedef struct drawctx {
+ OutFmt outfmt;
+ psbbox *bbox;
+} drawctx;
- printf("%f %f translate %f dup scale\n", ox, oy, scale);
- printf("%f setlinewidth\n", scale * 0.03);
- printf("0 setgray 1 setlinejoin 1 setlinecap\n");
-}
-
static void bbox_add_hat(void *vctx, Kite kite0, HatCoords *hc, int *coords)
{
- psbbox *bbox = (psbbox *)vctx;
+ drawctx *ctx = (drawctx *)vctx;
pspoint p;
size_t i;
@@ -1285,40 +1272,111 @@
for (i = 0; i < 14; i++) {
p.x = coords[2*i] * 1.5;
p.y = coords[2*i+1] * sqrt(0.75);
- psbbox_add(bbox, p);
+ psbbox_add(ctx->bbox, p);
}
}
+static void header(drawctx *ctx)
+{
+ switch (ctx->outfmt) {
+ case OF_POSTSCRIPT: {
+ float xext = ctx->bbox->tr.x - ctx->bbox->bl.x;
+ float yext = ctx->bbox->tr.y - ctx->bbox->bl.y;
+ float ext = (xext > yext ? xext : yext);
+ float scale = 500 / ext;
+ float ox = 287 - scale * (ctx->bbox->bl.x + ctx->bbox->tr.x) / 2;
+ float oy = 421 - scale * (ctx->bbox->bl.y + ctx->bbox->tr.y) / 2;
+
+ printf("%%!PS-Adobe-2.0\n%%%%Creator: hat-test from Simon Tatham's "
+ "Portable Puzzle Collection\n%%%%Pages: 1\n"
+ "%%%%BoundingBox: %f %f %f %f\n"
+ "%%%%EndComments\n%%%%Page: 1 1\n",
+ ox + scale * ctx->bbox->bl.x - 20,
+ oy + scale * ctx->bbox->bl.y - 20,
+ ox + scale * ctx->bbox->tr.x + 20,
+ oy + scale * ctx->bbox->tr.y + 20);
+
+ printf("%f %f translate %f dup scale\n", ox, oy, scale);
+ printf("%f setlinewidth\n", scale * 0.03);
+ printf("0 setgray 1 setlinejoin 1 setlinecap\n");
+ break;
+ }
+ default:
+ break;
+ }
+}
+
static void draw_hat(void *vctx, Kite kite0, HatCoords *hc, int *coords)
{
+ drawctx *ctx = (drawctx *)vctx;
pspoint p;
size_t i;
- const char *colour;
+ int orientation;
- printf("newpath");
- for (i = 0; i < 14; i++) {
- p.x = coords[2*i] * 1.5;
- p.y = coords[2*i+1] * sqrt(0.75);
- printf(" %f %f %s", p.x, p.y, i ? "lineto" : "moveto");
+ /*
+ * Determine an index for the hat's orientation, based on the axis
+ * of symmetry of its kite #0.
+ */
+ {
+ int dx = kite0.outer.x - kite0.centre.x;
+ int dy = kite0.outer.y - kite0.centre.y;
+ orientation = 0;
+ while (dx < 0 || dy < 0) {
+ int newdx = dx + dy;
+ int newdy = -dx;
+ dx = newdx;
+ dy = newdy;
+ orientation++;
+ assert(orientation < 6);
+ }
}
- printf(" closepath gsave");
- if (hc->c[2].type == TT_H) {
- colour = (hc->c[1].index == 3 ? "0 0.5 0.8 setrgbcolor" :
- "0.6 0.8 1 setrgbcolor");
- } else if (hc->c[2].type == TT_F) {
- colour = "0.7 setgray";
- } else {
- colour = "1 setgray";
+
+ switch (ctx->outfmt) {
+ case OF_POSTSCRIPT: {
+ const char *colour;
+
+ printf("newpath");
+ for (i = 0; i < 14; i++) {
+ p.x = coords[2*i] * 1.5;
+ p.y = coords[2*i+1] * sqrt(0.75);
+ printf(" %f %f %s", p.x, p.y, i ? "lineto" : "moveto");
+ }
+ printf(" closepath gsave");
+ if (hc->c[2].type == TT_H) {
+ colour = (hc->c[1].index == 3 ? "0 0.5 0.8 setrgbcolor" :
+ "0.6 0.8 1 setrgbcolor");
+ } else if (hc->c[2].type == TT_F) {
+ colour = "0.7 setgray";
+ } else {
+ colour = "1 setgray";
+ }
+ printf(" %s fill grestore", colour);
+ printf(" stroke\n");
+ break;
+ }
+ case OF_PYTHON: {
+ printf("hat('%c', %d, %d, [", "HTPF"[hc->c[2].type], hc->c[1].index,
+ orientation);
+ for (i = 0; i < 14; i++)
+ printf("%s(%d,%d)", i ? ", " : "", coords[2*i], coords[2*i+1]);
+ printf("])\n");
+ break;
+ }
}
- printf(" %s fill grestore", colour);
- printf(" stroke\n");
}
-static void trailer(void)
+static void trailer(drawctx *dctx)
{
- printf("showpage\n");
- printf("%%%%Trailer\n");
- printf("%%%%EOF\n");
+ switch (dctx->outfmt) {
+ case OF_POSTSCRIPT: {
+ printf("showpage\n");
+ printf("%%%%Trailer\n");
+ printf("%%%%EOF\n");
+ break;
+ }
+ default:
+ break;
+ }
}
int main(int argc, char **argv)
@@ -1331,7 +1389,10 @@
int w = 10, h = 10;
int argpos = 0;
size_t i;
+ drawctx dctx[1];
+ dctx->outfmt = OF_POSTSCRIPT;
+
while (--argc > 0) {
const char *arg = *++argv;
if (!strcmp(arg, "--help")) {
@@ -1340,6 +1401,8 @@
return 0;
} else if (!strcmp(arg, "--test")) {
return unit_tests() ? 0 : 1;
+ } else if (!strcmp(arg, "--python")) {
+ dctx->outfmt = OF_PYTHON;
} else if (arg[0] == '-') {
fprintf(stderr, "unrecognised option '%s'\n", arg);
return 1;
@@ -1364,17 +1427,18 @@
init_coords_random(ctx, rs);
bbox->started = false;
+ dctx->bbox = bbox;
first_kite(s, w, h);
coords[s->curr_index] = initial_coords(ctx);
maybe_report_hat(w, h, *s->curr, coords[s->curr_index],
- bbox_add_hat, bbox);
+ bbox_add_hat, dctx);
while (next_kite(s)) {
hc_free(coords[s->curr_index]);
coords[s->curr_index] = step_coords(
ctx, coords[s->last_index], s->last_step);
maybe_report_hat(w, h, *s->curr, coords[s->curr_index],
- bbox_add_hat, bbox);
+ bbox_add_hat, dctx);
}
for (i = 0; i < lenof(coords); i++) {
hc_free(coords[i]);
@@ -1381,18 +1445,18 @@
coords[i] = NULL;
}
- header(bbox);
+ header(dctx);
first_kite(s, w, h);
coords[s->curr_index] = initial_coords(ctx);
maybe_report_hat(w, h, *s->curr, coords[s->curr_index],
- draw_hat, NULL);
+ draw_hat, dctx);
while (next_kite(s)) {
hc_free(coords[s->curr_index]);
coords[s->curr_index] = step_coords(
ctx, coords[s->last_index], s->last_step);
maybe_report_hat(w, h, *s->curr, coords[s->curr_index],
- draw_hat, NULL);
+ draw_hat, dctx);
}
for (i = 0; i < lenof(coords); i++) {
hc_free(coords[i]);
@@ -1399,7 +1463,7 @@
coords[i] = NULL;
}
- trailer();
+ trailer(dctx);
cleanup_coords(ctx);