]> git.neil.brown.name Git - edlib.git/commitdiff
Add Draw:image-size and don't upscale images in emails.
authorNeilBrown <neil@brown.name>
Sat, 28 May 2022 23:37:49 +0000 (09:37 +1000)
committerNeilBrown <neil@brown.name>
Sat, 3 Sep 2022 06:49:09 +0000 (16:49 +1000)
New display function Draw:image-size reports the size of an image in
(x,y).
This is used when drawing an image with new attr noupscale to
ensure the size of the image is never scaled up, only down.

email now requests noupscale

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
display-x11-xcb.c
doc-email.c
lib-renderline.c
python/display-pygtk.py

index 02f2ec1773d12dbffd1ccd03d2351d16c59974dd..1632e05b57a1c1d4473ee0635338bc84f7ab808b 100644 (file)
@@ -43,7 +43,7 @@ Bugs to be fixed
 - [X] long lines wrap badly in xcb display - in emails at least
 - [ ] accessing document list can be slow.  Same for large directories
 - [X] queries don't update in the background - they used to
-- [ ] images in email message should never be scaled up
+- [X] images in email message should never be scaled up
 - [ ] marks sometimes get out of order in email query list
 - [X] C-y sometimes yanks something strange, A-y then needed.
 - [X] fill-mode doesn't propogate 'cols' from one instance to next
@@ -67,8 +67,8 @@ Bugs to be fixed
 - [X] invalid quoted-printable/utf8 content like We=E2&#128;&#153;d
       causes the rest of content not to be displayed.
 - [X] html2text should set decode-errors to ignore
-- [X] base64 saved-file of content ending 
-      IHdpZHRoPScxJyBoZWlnaHQ9JzEnID48L3NwYW4+IDwvYm9keT48L2h0bWw+DQo= 
+- [X] base64 saved-file of content ending
+      IHdpZHRoPScxJyBoZWlnaHQ9JzEnID48L3NwYW4+IDwvYm9keT48L2h0bWw+DQo=
       adds 0x40 0xff to the end.
 - [X] this highlighted added by xterm-keyboard-paste is disabled when chars
       are typed, but not on 'enter'
@@ -273,7 +273,7 @@ Module features
 ### rexel
 
 - [X] add "get-prefix" function to extract the longest constant
-      prefix from the pattern, so that a 'strstr' can be used to expedite 
+      prefix from the pattern, so that a 'strstr' can be used to expedite
       search
 - [ ] move to separate git repo and document well.
 - [ ] review return code of rxl_advance().  What should be
index d727d2b0da1463f07e25fbba3b4d7d535c95ec28..cac2de7117953ab612e6ba9697db89627559bf65 100644 (file)
@@ -884,6 +884,49 @@ DEF_CMD(xcb_draw_image)
        return 1;
 }
 
+DEF_CMD(xcb_image_size)
+{
+       MagickBooleanType status;
+       MagickWand *wd;
+       int ih, iw;
+
+       if (!ci->str)
+               return Enoarg;
+       if (strncmp(ci->str, "file:", 5) == 0) {
+               wd = NewMagickWand();
+               status = MagickReadImage(wd, ci->str + 5);
+               if (status == MagickFalse) {
+                       DestroyMagickWand(wd);
+                       return Efail;
+               }
+       } else if (strncmp(ci->str, "comm:", 5) == 0) {
+               struct call_return cr;
+               wd = NewMagickWand();
+               cr = call_ret(bytes, ci->str+5, ci->focus, 0, NULL, ci->str2);
+               if (!cr.s) {
+                       DestroyMagickWand(wd);
+                       return Efail;
+               }
+               status = MagickReadImageBlob(wd, cr.s, cr.i);
+               free(cr.s);
+               if (status == MagickFalse) {
+                       DestroyMagickWand(wd);
+                       return Efail;
+               }
+       } else
+               return Einval;
+
+       MagickAutoOrientImage(wd);
+       ih = MagickGetImageHeight(wd);
+       iw = MagickGetImageWidth(wd);
+
+       DestroyMagickWand(wd);
+       comm_call(ci->comm2, "callback:size", ci->focus,
+                 0, NULL, NULL, 0, NULL, NULL,
+                 iw, ih);
+       return 1;
+}
+
 static struct panes *sort_split(struct panes *p)
 {
        /* consider 'p' to be a list of panes with
@@ -1866,6 +1909,7 @@ void edlib_init(struct pane *ed safe)
        key_add(xcb_map, "Draw:text-size", &xcb_text_size);
        key_add(xcb_map, "Draw:text", &xcb_draw_text);
        key_add(xcb_map, "Draw:image", &xcb_draw_image);
+       key_add(xcb_map, "Draw:image-size", &xcb_image_size);
        key_add(xcb_map, "Refresh:size", &xcb_refresh_size);
        key_add(xcb_map, "Refresh:postorder", &xcb_refresh_post);
        key_add(xcb_map, "all-displays", &xcb_notify_display);
index 4195e2f2c3bc370eeab5aaa7e9f6cf1ca8cda8a7..f9648f9a8a585bb7ef70e53ae83a70c517b29447 100644 (file)
@@ -224,7 +224,8 @@ DEF_CMD(email_image)
                return Enoarg;
        p = get_part(ci->home, ci->mark);
        doc_next(ci->focus, ci->mark);
-       asprintf(&c, "<image:comm:doc:multipart-%d-doc:get-bytes>\n", to_orig(p));
+       asprintf(&c, "<image:comm:doc:multipart-%d-doc:get-bytes,noupscale>\n",
+                to_orig(p));
        ret = comm_call(ci->comm2, "callback:render", ci->focus,
                        0, NULL, c);
        free(c);
index 617bbeaa03832d0304124a2abf3e0beb6cae188a..a4020d0680bd636f99be0e95146b2af1c64ad93b 100644 (file)
@@ -21,6 +21,7 @@
  *
  */
 
+#define _GNU_SOURCE /*  for asprintf */
 #include <stdio.h>
 #include "core.h"
 #include "misc.h"
@@ -410,8 +411,14 @@ static void render_image(struct pane *p safe, struct pane *focus safe,
                        int dodraw, int scale)
 {
        char *fname = NULL;
-       short width = p->parent->w/2, height = p->parent->h/2;
+       short width, height;
+       char *size = attr_find(p->attrs, "cached-size");
 
+       if (!size || sscanf(size, "%hdx%hd", &width, &height) != 2) {
+               size = NULL;
+               width = p->parent->w/2;
+               height = p->parent->h/2;
+       }
        while (*line == '<')
                line += 1;
 
@@ -426,6 +433,16 @@ static void render_image(struct pane *p safe, struct pane *focus safe,
                } else if (strncmp(line, "height:", 7) == 0) {
                        height = atoi(line + 7);
                        height = height * scale / 1000;
+               } else if (!size && fname && strncmp(line, "noupscale", 9) == 0) {
+                       struct call_return cr =
+                               home_call_ret(all, focus, "Draw:image-size",
+                                             p, 0, NULL, fname);
+                       if (cr.x > 0 && cr.x < p->parent->w)
+                               width = cr.x;
+                       if (cr.y > 0 && cr.y < p->parent->h)
+                               height = cr.y;
+                       asprintf(&size, "%hdx%hd", width, height);
+                       attr_set_str(&p->attrs, "cached-size", size);
                }
                line += len;
                line += strspn(line, ",");
index cbd1241cb95976ba32dcc8e2e1b1f1c96afa3f8f..657bf4f8a2fa69c4f36ce2b624537c4385745839 100644 (file)
@@ -310,6 +310,24 @@ class EdDisplay(edlib.Pane):
         cr.paint()
         return True
 
+    def handle_image_size(self, key, focus, str1, str2, comm2, **a):
+        "handle:Draw:image-size"
+        if not str1 or not comm2:
+            return edlib.Enoarg
+        try:
+            if str1.startswith("file:"):
+                pb = GdkPixbuf.Pixbuf.new_from_file(str1[5:])
+            elif str1.startswith("comm:"):
+                img = focus.call(str1[5:], str2, ret='bytes')
+                io = Gio.MemoryInputStream.new_from_data(img)
+                pb = GdkPixbuf.Pixbuf.new_from_stream(io)
+            else:
+                return edlib.Einval
+        except:
+            return edlib.Einval
+        comm2("cb:size", focus, (pb.get_width(), pb.get_height()))
+        return True
+
     def handle_notify_close(self, key, focus, **a):
         "handle:Notify:Close"
         if focus and focus in self.panes: