aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devel.but20
-rw-r--r--emcc.c6
-rw-r--r--gtk.c4
-rw-r--r--midend.c56
-rw-r--r--nestedvm.c4
-rw-r--r--osx.m6
-rw-r--r--puzzles.h3
-rw-r--r--windows.c8
8 files changed, 87 insertions, 20 deletions
diff --git a/devel.but b/devel.but
index d2b9cac..9f734e1 100644
--- a/devel.but
+++ b/devel.but
@@ -2972,7 +2972,7 @@ when finished with by passing it to the game's own
\H{midend-size} \cw{midend_size()}
-\c void midend_size(midend *me, int *x, int *y, bool user_size);
+\c void midend_size(midend *me, int *x, int *y, bool user_size, double device_pixel_ratio);
Tells the mid-end to figure out its window size.
@@ -3029,6 +3029,24 @@ to use scroll bars for large puzzles), you can pass dimensions of
\cw{INT_MAX} as input to this function. You should probably not do
that \e{and} set the \c{user_size} flag, though!
+The \cw{device_pixel_ratio} allows the front end to specify that its
+pixels are unusually large or small (or should be treated as such).
+The mid-end uses this to adjust the tile size, both at startup (if the
+ratio is not 1) and if the ratio changes.
+
+A \cw{device_pixel_ratio} of 1 indicates normal-sized pixels.
+\q{Normal} is not precisely defined, but it's about 4 pixels per
+millimetre on a screen designed to be viewed from a metre away, or a
+size such that text 15 pixels high is comfortably readable. Some
+platforms have a concept of a logical pixel that this can be mapped
+onto. For instance, Cascading Style Sheets (CSS) has a unit called
+\cq{px} that only matches physical pixels at a \cw{device_pixel_ratio}
+of 1.
+
+The \cw{device_pixel_ratio} indicates the number of physical pixels in
+a normal-sized pixel, so values less than 1 indicate unusually large
+pixels and values greater than 1 indicate unusually small pixels.
+
The midend relies on the frontend calling \cw{midend_new_game()}
(\k{midend-new-game}) before calling \cw{midend_size()}.
diff --git a/emcc.c b/emcc.c
index 651fc5a..b7af686 100644
--- a/emcc.c
+++ b/emcc.c
@@ -195,7 +195,7 @@ static void resize(bool initial)
int w, h;
double dpr;
w = h = INT_MAX;
- midend_size(me, &w, &h, false);
+ midend_size(me, &w, &h, false, 1.0);
if (initial) {
dpr = js_get_device_pixel_ratio();
if (dpr != 1.0) {
@@ -207,7 +207,7 @@ static void resize(bool initial)
*/
w *= dpr;
h *= dpr;
- midend_size(me, &w, &h, true);
+ midend_size(me, &w, &h, true, 1.0);
}
}
js_canvas_set_size(w, h);
@@ -219,7 +219,7 @@ static void resize(bool initial)
/* Called from JS when the device pixel ratio changes */
void rescale_puzzle(int w, int h)
{
- midend_size(me, &w, &h, true);
+ midend_size(me, &w, &h, true, 1.0);
if (canvas_w != w || canvas_h != h) {
js_canvas_set_size(w, h);
canvas_w = w;
diff --git a/gtk.c b/gtk.c
index 2373e38..3ded45a 100644
--- a/gtk.c
+++ b/gtk.c
@@ -1674,7 +1674,7 @@ static void resize_puzzle_to_area(frontend *fe, int x, int y)
fe->w = x;
fe->h = y;
- midend_size(fe->me, &x, &y, true);
+ midend_size(fe->me, &x, &y, true, 1.0);
fe->pw = x;
fe->ph = y;
#if GTK_CHECK_VERSION(3,10,0)
@@ -2210,7 +2210,7 @@ static void get_size(frontend *fe, int *px, int *py)
*/
x = INT_MAX;
y = INT_MAX;
- midend_size(fe->me, &x, &y, false);
+ midend_size(fe->me, &x, &y, false, 1.0);
*px = x;
*py = y;
}
diff --git a/midend.c b/midend.c
index 2489803..a8f9cf3 100644
--- a/midend.c
+++ b/midend.c
@@ -89,7 +89,8 @@ struct midend {
int pressed_mouse_button;
- int preferred_tilesize, tilesize, winwidth, winheight;
+ int preferred_tilesize, preferred_tilesize_dpr, tilesize;
+ int winwidth, winheight;
void (*game_id_change_notify_function)(void *);
void *game_id_change_notify_ctx;
@@ -130,11 +131,14 @@ static const char *midend_deserialise_internal(
void midend_reset_tilesize(midend *me)
{
me->preferred_tilesize = me->ourgame->preferred_tilesize;
+ me->preferred_tilesize_dpr = 1.0;
{
/*
* Allow an environment-based override for the default tile
* size by defining a variable along the lines of
* `NET_TILESIZE=15'.
+ *
+ * XXX How should this interact with DPR?
*/
char buf[80], *e;
@@ -306,10 +310,50 @@ static void midend_size_new_drawstate(midend *me)
}
}
-void midend_size(midend *me, int *x, int *y, bool user_size)
+/*
+ * There is no one correct way to convert tilesizes between device
+ * pixel ratios, because there's only a loosely-defined relationship
+ * between tilesize and the actual size of a puzzle. We define this
+ * function as the canonical conversion function so everything in the
+ * midend will be consistent.
+ */
+static int convert_tilesize(midend *me, int old_tilesize,
+ double old_dpr, double new_dpr)
+{
+ int x, y, rx, ry, min, max, mid;
+ game_params *defaults = me->ourgame->default_params();
+
+ if (new_dpr == old_dpr)
+ return old_tilesize;
+ me->ourgame->compute_size(defaults, old_tilesize, &x, &y);
+ x *= new_dpr / old_dpr;
+ y *= new_dpr / old_dpr;
+
+ min = max = 1;
+ do {
+ max *= 2;
+ me->ourgame->compute_size(defaults, max, &rx, &ry);
+ } while (rx <= x && ry <= y);
+
+ while (max - min > 1) {
+ int mid = (max + min) / 2;
+ me->ourgame->compute_size(defaults, mid, &rx, &ry);
+ if (rx <= x && ry <= y)
+ min = mid;
+ else
+ max = mid;
+ }
+
+ me->ourgame->free_params(defaults);
+ return min;
+}
+
+void midend_size(midend *me, int *x, int *y, bool user_size,
+ double device_pixel_ratio)
{
int min, max;
int rx, ry;
+ int preferred_tilesize;
/*
* We can't set the size on the same drawstate twice. So if
@@ -339,7 +383,9 @@ void midend_size(midend *me, int *x, int *y, bool user_size)
me->ourgame->compute_size(me->params, max, &rx, &ry);
} while (rx <= *x && ry <= *y);
} else
- max = me->preferred_tilesize + 1;
+ max = convert_tilesize(me, me->preferred_tilesize,
+ me->preferred_tilesize_dpr,
+ device_pixel_ratio) + 1;
min = 1;
/*
@@ -362,9 +408,11 @@ void midend_size(midend *me, int *x, int *y, bool user_size)
*/
me->tilesize = min;
- if (user_size)
+ if (user_size) {
/* If the user requested a change in size, make it permanent. */
me->preferred_tilesize = me->tilesize;
+ me->preferred_tilesize_dpr = device_pixel_ratio;
+ }
midend_size_new_drawstate(me);
*x = me->winwidth;
*y = me->winheight;
diff --git a/nestedvm.c b/nestedvm.c
index 947abe0..ec633d3 100644
--- a/nestedvm.c
+++ b/nestedvm.c
@@ -217,7 +217,7 @@ int jcallback_resize(int width, int height)
int x, y;
x = width;
y = height;
- midend_size(fe->me, &x, &y, true);
+ midend_size(fe->me, &x, &y, true, 1.0);
fe->ox = (width - x) / 2;
fe->oy = (height - y) / 2;
fe->w = x;
@@ -358,7 +358,7 @@ static void resize_fe(frontend *fe)
x = INT_MAX;
y = INT_MAX;
- midend_size(fe->me, &x, &y, false);
+ midend_size(fe->me, &x, &y, false, 1.0);
_call_java(3, x, y, 0);
}
diff --git a/osx.m b/osx.m
index 36e9693..646cffc 100644
--- a/osx.m
+++ b/osx.m
@@ -524,7 +524,7 @@ struct frontend {
frame.origin.x = 0;
w = h = INT_MAX;
- midend_size(me, &w, &h, false);
+ midend_size(me, &w, &h, false, 1.0);
frame.size.width = w;
frame.size.height = h;
fe.w = w;
@@ -559,7 +559,7 @@ struct frontend {
*/
midend_new_game(me);
w = h = INT_MAX;
- midend_size(me, &w, &h, false);
+ midend_size(me, &w, &h, false, 1.0);
rect.size.width = w;
rect.size.height = h;
fe.w = w;
@@ -959,7 +959,7 @@ struct frontend {
int w, h;
w = h = INT_MAX;
- midend_size(me, &w, &h, false);
+ midend_size(me, &w, &h, false, 1.0);
size.width = w;
size.height = h;
fe.w = w;
diff --git a/puzzles.h b/puzzles.h
index f0a7e99..1d4dd33 100644
--- a/puzzles.h
+++ b/puzzles.h
@@ -299,7 +299,8 @@ void midend_free(midend *me);
const game *midend_which_game(midend *me);
void midend_set_params(midend *me, game_params *params);
game_params *midend_get_params(midend *me);
-void midend_size(midend *me, int *x, int *y, bool user_size);
+void midend_size(midend *me, int *x, int *y, bool user_size,
+ double device_pixel_ratio);
void midend_reset_tilesize(midend *me);
void midend_new_game(midend *me);
void midend_restart_game(midend *me);
diff --git a/windows.c b/windows.c
index aa95b62..e58a150 100644
--- a/windows.c
+++ b/windows.c
@@ -1285,7 +1285,7 @@ static bool check_window_resize(frontend *fe, int cx, int cy,
* See if we actually got the window size we wanted, and adjust
* the puzzle size if not.
*/
- midend_size(fe->me, &x, &y, true);
+ midend_size(fe->me, &x, &y, true, 1.0);
if (x != cx || y != cy) {
/*
* Resize the window, now we know what size we _really_
@@ -1611,7 +1611,7 @@ static int fe_set_midend(frontend *fe, midend *me)
fe->statusbar = NULL;
get_max_puzzle_size(fe, &x, &y);
- midend_size(fe->me, &x, &y, false);
+ midend_size(fe->me, &x, &y, false, 1.0);
r.left = r.top = 0;
r.right = x;
@@ -2374,12 +2374,12 @@ static void new_game_size(frontend *fe, float scale)
int x, y;
get_max_puzzle_size(fe, &x, &y);
- midend_size(fe->me, &x, &y, false);
+ midend_size(fe->me, &x, &y, false, 1.0);
if (scale != 1.0) {
x = (int)((float)x * fe->puzz_scale);
y = (int)((float)y * fe->puzz_scale);
- midend_size(fe->me, &x, &y, true);
+ midend_size(fe->me, &x, &y, true, 1.0);
}
fe->ymin = (fe->xmin * y) / x;