shithub: puzzles

Download patch

ref: 1e8169ea94da3c37fc8fbe38ccb8120ae540743a
parent: fa58dd85b7ee06fed8d7a5ecc14fda8146f7521b
author: Ben Harris <bjh21@bjh21.me.uk>
date: Thu Oct 27 18:37:31 EDT 2022

js: Take device pixel ratio into account when setting default size

This is a bit of a hack.  When setting the puzzle to its default size,
either at startup or from a right-click on the resize handle, we now
scale the default size from midend_size() by the device pixel ratio,
and then pass that back to midend_size().  This does more or less the
right thing, in that the puzzle now starts up at a size that scales
with the font size.

There are still some slight inconsistencies, where sequences of DPR
changes and puzzle parameter changes can have order-dependent effects
on the size of the puzzle.  Happily these effects are small and fairly
hard to observe.

--- a/emcc.c
+++ b/emcc.c
@@ -83,6 +83,7 @@
 extern void js_canvas_set_statusbar(const char *text);
 extern void js_canvas_set_size(int w, int h);
 extern void js_canvas_set_nominal_size();
+extern double js_get_device_pixel_ratio();
 
 extern void js_dialog_init(const char *title);
 extern void js_dialog_string(int i, const char *title, const char *initvalue);
@@ -183,12 +184,32 @@
  */
 static int canvas_w, canvas_h;
 
-/* Called when we resize as a result of changing puzzle settings */
-static void resize(void)
+/* 
+ * Called when we resize as a result of changing puzzle settings.
+ * "initial" is true if this is the first call, or the first call
+ * since a midend_reset_tilesize().  In that case, we might want to
+ * adjust the size to compensate for the device pixel ratio.
+ */
+static void resize(bool initial)
 {
     int w, h;
+    double dpr;
     w = h = INT_MAX;
     midend_size(me, &w, &h, false);
+    if (initial) {
+        dpr = js_get_device_pixel_ratio();
+        if (dpr != 1.0) {
+            /*
+             * The default w and h are probably in units of
+             * sensible-sized pixels (~0.25 mm).  Scale them to the
+             * actual device pixels and then ask for a size near
+             * that.
+             */
+            w *= dpr;
+            h *= dpr;
+            midend_size(me, &w, &h, true);
+        }
+    }
     js_canvas_set_size(w, h);
     js_canvas_set_nominal_size();
     canvas_w = w;
@@ -218,7 +239,7 @@
 void restore_puzzle_size(int w, int h)
 {
     midend_reset_tilesize(me);
-    resize();
+    resize(true);
     midend_force_redraw(me);
 }
 
@@ -713,7 +734,7 @@
              */
             select_appropriate_preset();
             midend_new_game(me);
-            resize();
+            resize(false);
             midend_redraw(me);
             free_cfg(cfg);
             js_dialog_cleanup();
@@ -770,7 +791,7 @@
                 assert(i < npresets);
                 midend_set_params(me, presets[i]);
                 midend_new_game(me);
-                resize();
+                resize(false);
                 midend_redraw(me);
                 update_undo_redo();
                 js_focus_canvas();
@@ -894,7 +915,7 @@
         js_error_box(err);
     } else {
         select_appropriate_preset();
-        resize();
+        resize(false);
         midend_redraw(me);
         update_permalinks();
         update_undo_redo();
@@ -936,7 +957,7 @@
      * canvas size appropriately.
      */
     midend_new_game(me);
-    resize();
+    resize(true);
 
     /*
      * Create a status bar, if needed.
--- a/emcclib.js
+++ b/emcclib.js
@@ -570,6 +570,15 @@
     },
 
     /*
+     * double js_get_device_pixel_ratio();
+     *
+     * Return the current device pixel ratio.
+     */
+    js_get_device_pixel_ratio: function() {
+        return window.devicePixelRatio || 1;
+    },
+
+    /*
      * void js_dialog_init(const char *title);
      * 
      * Begin constructing a 'dialog box' which will be popped up in an