shithub: puzzles

Download patch

ref: 44b5291b48e77810a096933d0b6f8dae5a17300c
parent: 1ef9aa4cc26b60d63f134d5f7a3ff9331f8a8b50
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sun Jan 1 09:07:59 EST 2023

Adjust font size of Pattern clues based on the numbers

If all the column clues are single digits, then the font can be larger
without adjacent clues getting too close to each other.  I've also
slightly increased the font size even with two-digit clues, from
TILE_SIZE/2 to TILE_SIZE/1.8.

--- a/pattern.c
+++ b/pattern.c
@@ -53,6 +53,7 @@
     int *rowdata, *rowlen;
     bool *immutable;
     int refcount;
+    enum { FS_SMALL, FS_LARGE } fontsize;
 } game_state_common;
 
 struct game_state {
@@ -965,7 +966,7 @@
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
-    int i;
+    int i, j;
     const char *p;
     game_state *state = snew(game_state);
 
@@ -1003,6 +1004,16 @@
         }
     }
 
+    /*
+     * Choose a font size based on the clues.  If any column clue is
+     * more than one digit, switch to the smaller size.
+     */
+    state->common->fontsize = FS_LARGE;
+    for (i = 0; i < params->w; i++)
+        for (j = 0; j < state->common->rowlen[i]; j++)
+            if (state->common->rowdata[state->common->rowsize * i + j] >= 10)
+                state->common->fontsize = FS_SMALL;
+
     if (desc[-1] == ',') {
         /*
          * Optional extra piece of game description which fills in
@@ -1761,6 +1772,7 @@
     int nfit;
     int j;
     int rx, ry, rw, rh;
+    int fontsize;
 
     if (i < state->common->w) {
         rx = TOCOORD(state->common->w, i);
@@ -1779,6 +1791,24 @@
         draw_rect(dr, rx, ry, rw, rh, COL_BACKGROUND);
 
     /*
+     * Choose a font size that's suitable for the lengths of clue.
+     * Only column clues are interesting because row clues can be
+     * spaced out independent of the tile size.  For column clues, we
+     * want to go as large as practical while leaving decent space
+     * between horizintally adjacent clues.  We currently distinguish
+     * two cases: FS_LARGE is when all column clues are single digits,
+     * and FS_SMALL in all other cases.
+     *
+     * If we assume that a digit is about 0.6em wide, and we want
+     * about that space between clues, then FS_SMALL should be
+     * TILESIZE/1.2.  If we also assume that clues are at most two
+     * digits long then the case where adjacent clues are two digits
+     * long requries FS_LARGE to be TILESIZE/1.8.
+     */
+    fontsize = (TILE_SIZE + 0.5F) /
+        (state->common->fontsize == FS_LARGE ? 1.2F : 1.8F);
+
+    /*
      * Normally I space the numbers out by the same distance as the
      * tile size. However, if there are more numbers than available
      * spaces, I have to squash them up a bit.
@@ -1800,7 +1830,7 @@
             y -= ((rowlen-j-1)*TILE_SIZE) * (TLBORDER(state->common->h)-1) / nfit;
             sprintf(str, "%d", rowdata[j]);
             draw_text(dr, x+TILE_SIZE/2, y+TILE_SIZE/2, FONT_VARIABLE,
-                      TILE_SIZE/2, ALIGN_HCENTRE | ALIGN_VCENTRE, colour, str);
+                      fontsize, ALIGN_HCENTRE | ALIGN_VCENTRE, colour, str);
         }
     } else {
         int x, y;
@@ -1814,7 +1844,7 @@
         y = ry;
         x = BORDER + TILE_SIZE * (TLBORDER(state->common->w)-1);
         draw_text(dr, x+TILE_SIZE, y+TILE_SIZE/2, FONT_VARIABLE,
-                  TILE_SIZE/2, ALIGN_HRIGHT | ALIGN_VCENTRE, colour, str);
+                  fontsize, ALIGN_HRIGHT | ALIGN_VCENTRE, colour, str);
     }
 
     unclip(dr);