]> git.neil.brown.name Git - edlib.git/commitdiff
imageview: support requesting an integral zoom.
authorNeilBrown <neil@brown.name>
Fri, 6 Oct 2023 21:56:23 +0000 (08:56 +1100)
committerNeilBrown <neil@brown.name>
Sat, 7 Oct 2023 01:06:34 +0000 (12:06 +1100)
Some images (like QR code) don't do well when scaled non-integal
amounts.
So allow imageview to be told that integral scaling is needed.

Signed-off-by: NeilBrown <neil@brown.name>
render-imageview.c

index b274f7f0f04b365f1e2732b6f3007e5bb5947ab7..161514befcebed32dccee12276db26092c186d56 100644 (file)
@@ -17,6 +17,7 @@ struct imageview_data {
                         * Kept stable during zoom
                         */
        short px,py;    /* number of pixels in each pane cell */
+       bool integral;  /* Use integral scales */
 };
 #include "core-pane.h"
 
@@ -29,6 +30,18 @@ DEF_CMD_CLOSED(imageview_close)
        return 1;
 }
 
+static int fix_scale(struct imageview_data *ivd safe, int scale)
+{
+       if (!ivd->integral)
+               return scale;
+
+       if (scale >= 1024)
+               return scale & ~1023;
+       if (scale > 0)
+               return 1024 / (1024 / scale);
+       return scale;
+}
+
 DEF_CMD(imageview_refresh)
 {
        struct imageview_data *ivd = ci->home->data;
@@ -47,11 +60,15 @@ DEF_CMD(imageview_refresh)
                ivd->image = strdup(img);
 
        if (ivd->w <= 0) {
+               char *i;
                struct call_return cr = call_ret(all, "Draw:image-size",
                                                 ci->focus,
                                                 0, NULL, img);
                ivd->w = cr.x;
                ivd->h = cr.y;
+
+               i = pane_attr_get(ci->focus, "imageview:integral");
+               ivd->integral = (i && strcmp(i, "yes") == 0);
        }
        if (ivd->w <= 0 || ivd->h <= 0)
                return 1;
@@ -59,7 +76,7 @@ DEF_CMD(imageview_refresh)
        if (ivd->scale <= 0) {
                int xs = pw * 1024 / ivd->w;
                int ys = ph * 1024 / ivd->h;
-               ivd->scale = xs > ys ? ys : xs;
+               ivd->scale = fix_scale(ivd, xs > ys ? ys : xs);
        }
 
        x = (ivd->cx * ivd->scale) - pw * 1024 / 2;
@@ -114,13 +131,18 @@ DEF_CMD(imageview_zoom)
         * zooming.
         */
        struct imageview_data *ivd = ci->home->data;
+       int scale = ivd->scale;
 
        if (strcmp(ci->key, "K-+") == 0) {
                /* zoom up */
-               ivd->scale += ivd->scale / 10;
+               ivd->scale = fix_scale(ivd, scale + scale / 10);
+               if (ivd->scale == scale)
+                       ivd->scale += 1024;
        } else {
                /* zoom down */
-               ivd->scale -= ivd->scale / 11;
+               ivd->scale = fix_scale(ivd, scale - scale / 11);
+               if (ivd->scale == scale && scale > 1 && scale <= 1024)
+                       ivd->scale = 1024 / (1024 / scale + 1);
        }
 
        pane_damaged(ci->home, DAMAGED_REFRESH);
@@ -183,6 +205,7 @@ DEF_CMD(imageview_attach)
        if (ci->str)
                ivd->image = strdup(ci->str);
        ivd->scale = 0;
+       ivd->integral = False;
        pxl = pane_attr_get(p, "Display:pixels");
        if (sscanf(pxl ?: "1x1", "%hdx%hx", &ivd->px, &ivd->py) != 2)
                ivd->px = ivd->py = 1;