]> git.neil.brown.name Git - edlib.git/commitdiff
Move some common code from Draw:image implementations into lib-window
authorNeilBrown <neil@brown.name>
Fri, 29 Sep 2023 02:59:35 +0000 (12:59 +1000)
committerNeilBrown <neil@brown.name>
Fri, 29 Sep 2023 23:46:10 +0000 (09:46 +1000)
lib-window now provides Draw:scale-image which is used by Draw:image to
interpret the request and provide simple requests for the Drawing
engine.
pygtk doesn't use this yet.

Draw:scale-image should probably parse the file name etc too.

This fixes a bug in image display in ncurses where the image isn't
centred vertically when it isn't high enough to fill space.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
core-window.c
display-ncurses.c
display-x11-xcb.c
tests.d/02-presenter

index e7e1a65dc28fec81763b5b21092816691b229b85..d6cd3080c5ef65e7c4848694d3d2bd81116a034d 100644 (file)
@@ -34,6 +34,7 @@ the file.
 - [ ] selection-menu item for spell-check ??
 - [ ] notmuch - capture errors about multiple Subject lines and
       display them better.
+- [ ] switch display-pygtk to use Draw:scale-image
 
 ### Small
 
@@ -56,7 +57,7 @@ the file.
 
 ### Large
 
-- [ ] image-display pane
+- [X] image-display pane
 - [ ] git-mode
 - [ ] render-markdown.py
 - [X] lib-menu
@@ -194,12 +195,19 @@ Core features
 Module features
 ---------------
 
+### render-imageview
+
+- [ ] use a document, not a magic command.  This requires multipart
+      to be able to hand over a document
+- [ ] activate from file browser somehow
+- [ ] cache the decompressed image somewhere.
+
 ### lib-menubar
 
-- enable activation via F10.  Cancel makes it disappear if configed
-  not too.  How to keep??
-- allow left/right arrows to move between menus
-- emacs to disable 'save' when cannot be saved.
+- [ ] enable activation via F10.  Cancel makes it disappear if
+      configured not too.  How to keep??
+- [ ] allow left/right arrows to move between menus
+- [ ] emacs to disable 'save' when cannot be saved.
 
 ### lib-qrcode
 
@@ -1017,7 +1025,7 @@ Possibly some of these will end up being features in other modules.
       This might support a menu-bar, or drop-downs for spelling or dynamic completion.
 - [ ] hex edit block device - mmap document type
 
-- [ ] image-display pane - e.g. can be given a png/jpeg etc file and display
+- [X] image-display pane - e.g. can be given a png/jpeg etc file and display
       it scaled, plus allow scaling and movement
 - [ ] pdf-display pane - like image-display but with multiple pages.
       Would use libpoppler.
index e763702b58a8bef4abd534020420c148e06d5912..54c7ec25fd8e83726fa5e5b12f4ea95e4e86d43d 100644 (file)
@@ -138,6 +138,139 @@ DEF_CMD(selection_discard)
        return 1;
 }
 
+DEF_CMD(scale_image)
+{
+       /* This is a helper for Draw:image which interprets str2
+        * with other values and calls comm2 with:
+        * "width" returns image width
+        * "height" returns image height
+        * "scale"  num=new width, num2=new height
+        * "crop" x,y is top-left num,num2 - width,height
+        *          These numbers apply after scaling.
+        * "draw"  num,num2 = offset
+        * "cursor" x,y=pos, num,num2=size
+        *
+        * Inputs are:
+        * 'str2' container 'mode' information.
+        *     By default the image is placed centrally in the pane
+        *     and scaled to use either fully height or fully width.
+        *     Various letters modify this:
+        *     'S' - stretch to use full height *and* full width
+        *     'L' - place on left if full width isn't used
+        *     'R' - place on right if full width isn't used
+        *     'T' - place at top if full height isn't used
+        *     'B' - place at bottom if full height isn't used.
+        *
+        *    Also a suffix ":NNxNN" will be parse and the two numbers used
+        *    to give number of rows and cols to overlay on the image for
+        *    the purpose of cursor positioning.  If these are present and
+        *    p->cx,cy are not negative, draw a cursor at p->cx,cy highlighting
+        *    the relevant cell.
+        *
+        * num,num2, if both positive, override the automatic scaling.
+        *    The image is scaled to this many pixels.
+        * x,y is top-left pixel in the scaled image to start display at.
+        *    Negative values allow a margin between pane edge and this image.
+        */
+       struct pane *p = ci->focus;
+       const char *mode = ci->str2 ?: "";
+       bool stretch = strchr(mode, 'S');
+       int w, h;
+       int x = 0, y = 0;
+       int pw, ph;
+       int xo = 0, yo = 0;
+       int cix, ciy;
+       const char *pxl;
+       short px, py;
+
+       if (!ci->comm2)
+               return Enoarg;
+
+       pxl = pane_attr_get(p, "Display:pixels");
+       if (sscanf(pxl ?: "1x1", "%hdx%hx", &px, &py) != 2)
+               px = py = 1;
+
+       w = p->w * px;
+       h = p->h * py;
+       if (ci->num > 0 && ci->num2 > 0) {
+               w = ci->num;
+               h = ci->num2;
+       } else if (ci->num > 0) {
+               int iw = comm_call(ci->comm2, "width", p);
+               int ih = comm_call(ci->comm2, "height", p);
+
+               if (iw <= 0 || ih <= 0)
+                       return Efail;
+
+               w = iw * ci->num / 1024;
+               h = ih * ci->num / 1024;
+       } else if (!stretch) {
+               int iw = comm_call(ci->comm2, "width", p);
+               int ih = comm_call(ci->comm2, "height", p);
+
+               if (iw <= 0 || ih <= 0)
+                       return Efail;
+
+               if (iw * h > ih * w) {
+                       /* Image is wider than space, use less height */
+                       ih = ih * w / iw;
+                       if (strchr(mode, 'B'))
+                               /* bottom */
+                               y = h - ih;
+                       else if (!strchr(mode, 'T'))
+                               /* center */
+                               y = (h - ih) / 2;
+                       /* Round up to pixels-per-cell */
+                       h = ((ih + py - 1) / py) * py;
+               } else {
+                       /* image is too tall, use less width */
+                       iw = iw * h / ih;
+                       if (strchr(mode, 'R'))
+                               /* right */
+                               x = w - iw;
+                       else if (!strchr(mode, 'L'))
+                               x = (w - iw) / 2;
+                       w = ((iw + px - 1) / px) * px;
+               }
+       }
+
+       comm_call(ci->comm2, "scale", p, w, NULL, NULL, h);
+       pw = p->w * px;
+       ph = p->h * py;
+       cix = ci->x;
+       ciy = ci->y;
+       if (cix < 0) {
+               xo -= cix;
+               pw += cix;
+               cix = 0;
+       }
+       if (ciy < 0) {
+               yo -= ciy;
+               ph += ciy;
+               ciy = 0;
+       }
+       if (w - cix <= pw)
+               w -= cix;
+       else
+               w = pw;
+       if (h - ciy <= ph)
+               h -= ciy;
+       else
+               h = ph;
+       comm_call(ci->comm2, "crop", p, w, NULL, NULL, h, NULL, NULL, cix, ciy);
+       comm_call(ci->comm2, "draw", p, x + xo, NULL, NULL, y + yo);
+
+       if (p->cx >= 0) {
+               int rows, cols;
+               char *cl = strchr(mode, ':');
+               if (cl && sscanf(cl, ":%dx%d", &cols, &rows) == 2)
+                       comm_call(ci->comm2, "cursor", p,
+                                 w/cols, NULL, NULL, h/rows, NULL, NULL,
+                                 p->cx + xo, p->cy + yo);
+       }
+       return 1;
+}
+
 DEF_CMD(close_notify)
 {
        struct window_data *wd = ci->home->data;
@@ -186,6 +319,8 @@ void window_setup(struct pane *ed safe)
        key_add(window_map, "selection:discard", &selection_discard);
        key_add(window_map, "Notify:Close", &close_notify);
 
+       key_add(window_map, "Draw:scale-image", &scale_image);
+
        call_comm("global-set-command", ed, &window_attach, 0, NULL,
                  "attach-window-core");
 }
index 69cd0fe733d7b00ccb5c3ad1d1cfcc1a599fdcca..ee8ce70db64af4366808912674d4b51bab452d78 100644 (file)
@@ -995,46 +995,120 @@ DEF_CMD(nc_draw_text)
        return 1;
 }
 
+struct di_info {
+       struct command c;
+       MagickWand *wd safe;
+       int x,y,w,h;
+       int xo, yo;
+       struct pane *p safe;
+};
+
+DEF_CB(nc_draw_image_cb)
+{
+       struct di_info *dii = container_of(ci->comm, struct di_info, c);
+       struct display_data *dd = dii->p->data;
+       int i, j;
+       unsigned char *buf;
+
+       switch (ci->key[0]) {
+       case 'w': /* width */
+               return MagickGetImageWidth(dii->wd);
+       case 'h': /* height */
+               return MagickGetImageHeight(dii->wd);
+       case 's': /* scale */
+               MagickAdaptiveResizeImage(dii->wd, ci->num, ci->num2);
+               return 1;
+       case 'c': /* crop or cursor */
+               if (ci->key[1] != 'u') {
+                       /* crop */
+                       dii->x = ci->x;
+                       dii->y = ci->y;
+                       dii->w = ci->num;
+                       dii->h = ci->num2;
+                       return 1;
+               } else {
+                       /* cursor */
+                       /* FIXME this doesn't work because
+                        * render-line knows too much and gets it wrong.
+                        */
+                       ncurses_text(ci->focus, dii->p, 'X', 0,
+                                    to_pair(dd, 0, 0),
+                                    ci->x + dii->xo,
+                                    (ci->y + dii->xo)/2, 1);
+                       return 1;
+               }
+       case 'd': /* draw */
+               if (dii->w <= 0 || dii->h <= 0)
+                       return Efail;
+               buf = malloc(dii->h * dii->w * 4);
+
+               MagickExportImagePixels(dii->wd, dii->x, dii->y,
+                                       dii->w, dii->h,
+                                       "RGBA", CharPixel, buf);
+
+               for (i = 0; i < dii->h; i+= 2) {
+                       static const wint_t hilo = 0x2580; /* L'▀' */
+                       for (j = 0; j < dii->w ; j+= 1) {
+                               unsigned char *p1 = buf + i*dii->w*4 + j*4;
+                               unsigned char *p2 = buf + (i+1)*dii->w*4 + j*4;
+                               int rgb1[3] = { p1[0]*1000/255, p1[1]*1000/255, p1[2]*1000/255 };
+                               int rgb2[3] = { p2[0]*1000/255, p2[1]*1000/255, p2[2]*1000/255 };
+                               int fg = find_col(dd, rgb1);
+                               int bg = find_col(dd, rgb2);
+
+                               if (p1[3] < 128 || p2[3] < 128) {
+                                       /* transparent */
+                                       cchar_t cc;
+                                       short f,b;
+                                       struct pane *pn2 = ci->focus;
+                                       PANEL *pan = pane_panel(pn2, NULL);
+
+                                       while (!pan && pn2->parent != pn2) {
+                                               pn2 = pn2->parent;
+                                               pan = pane_panel(pn2, NULL);
+                                       }
+                                       if (pan) {
+                                               wgetbkgrnd(panel_window(pan), &cc);
+                                               if (cc.ext_color == 0)
+                                                       /* default.  This is light
+                                                        * gray rather then white,
+                                                        * but I think it is a good
+                                                        * result.
+                                                        */
+                                                       b = COLOR_WHITE;
+                                               else
+                                                       pair_content(cc.ext_color, &f, &b);
+                                               if (p1[3] < 128)
+                                                       fg = b;
+                                               if (p2[3] < 128)
+                                                       bg = b;
+                                       }
+                               }
+                               ncurses_text(ci->focus, dii->p, hilo, 0,
+                                            to_pair(dd, fg, bg),
+                                            ci->num + dii->xo + j,
+                                            (ci->num2 + dii->yo + i)/2,
+                                            0);
+                       }
+               }
+               free(buf);
+               return 1;
+       default:
+               return Efail;
+       }
+}
+
 DEF_CMD(nc_draw_image)
 {
        /* 'str' identifies the image. Options are:
         *     file:filename  - load file from fs
         *     comm:command   - run command collecting bytes
-        * 'str2' container 'mode' information.
-        *     By default the image is placed centrally in the pane
-        *     and scaled to use either fully height or fully width.
-        *     Various letters modify this:
-        *     'S' - stretch to use full height *and* full width
-        *     'L' - place on left if full width isn't used
-        *     'R' - place on right if full width isn't used
-        *     'T' - place at top if full height isn't used
-        *     'B' - place at bottom if full height isn't used.
-        *
-        *    Also a suffix ":NNxNN" will be parse and the two numbers used
-        *    to give number of rows and cols to overlay on the image for
-        *    the purpose of cursor positioning.  If these are present and
-        *    p->cx,cy are not negative, draw a cursor at p->cx,cy highlighting
-        *    the relevant cell.
-        *
-        * num,num2, if both positive, override the automatic scaling.
-        *    The image is scaled to this many pixels.
-        * x,y is top-left pixel in the scaled image to start display at.
-        *    Negative values allow a margin between pane edge and this image.
+        * 'str2' and numbers are handled by Draw:scale-image.
         */
        struct pane *p = ci->home;
-       struct display_data *dd = p->data;
-       int x = 0, y = 0;
-       const char *mode = ci->str2 ?: "";
-       bool stretch = strchr(mode, 'S');
-       int w = ci->focus->w, h = ci->focus->h * 2;
-       int pw = w, ph = h;
-       int xo = 0, yo = 0;
-       int cix, ciy;
-       int cx = -1, cy = -1;
        MagickBooleanType status;
-       MagickWand *wd;
-       unsigned char *buf;
-       int i, j;
+       MagickWand *wd = NULL;
+       struct di_info dii;
 
        if (!ci->str)
                return Enoarg;
@@ -1059,135 +1133,19 @@ DEF_CMD(nc_draw_image)
                        DestroyMagickWand(wd);
                        return Efail;
                }
-       } else
+       }
+
+       if (!wd)
                return Einval;
 
        MagickAutoOrientImage(wd);
-       if (ci->num > 0 && ci->num2 > 0) {
-               w = ci->num;
-               h = ci->num2;
-       } else if (ci->num > 0) {
-               int ih = MagickGetImageHeight(wd);
-               int iw = MagickGetImageWidth(wd);
-
-               if (iw <= 0 || iw <= 0) {
-                       DestroyMagickWand(wd);
-                       return Efail;
-               }
-               w = iw * ci->num / 1024;
-               h = ih * ci->num / 1024;
-       } else if (!stretch) {
-               int ih = MagickGetImageHeight(wd);
-               int iw = MagickGetImageWidth(wd);
-
-               if (iw <= 0 || iw <= 0) {
-                       DestroyMagickWand(wd);
-                       return Efail;
-               }
-               if (iw * h > ih * w) {
-                       /* Image is wider than space, use less height */
-                       ih = ih * w / iw;
-                       if (strchr(mode, 'B'))
-                               /* bottom */
-                               y = h - ih;
-                       else if (!strchr(mode, 'T'))
-                               /* center */
-                               y = (h - ih) / 2;
-                       /* Keep 'h' even! */
-                       h = ((ih+1)/2) * 2;
-               } else {
-                       /* image is too tall, use less width */
-                       iw = iw * h / ih;
-                       if (strchr(mode, 'R'))
-                               /* right */
-                               x = w - iw;
-                       else if (!strchr(mode, 'L'))
-                               x = (w - iw) / 2;
-                       w = iw;
-               }
-       }
-       MagickAdaptiveResizeImage(wd, w, h);
-       cix = ci->x;
-       ciy = ci->y;
-       if (cix < 0) {
-               xo -= cix;
-               pw += cix;
-               cix = 0;
-       }
-       if (ciy < 0) {
-               yo -= ciy;
-               ph += ciy;
-               ciy = 0;
-       }
-       if (w - cix <= pw)
-               w -= cix;
-       else
-               w = pw;
-       if (h - ciy <= ph)
-               h -= ciy;
-       else
-               h = ph;
-       buf = malloc(h * w * 4);
-       MagickExportImagePixels(wd, cix, ciy, w, h, "RGBA", CharPixel, buf);
-
-       if (ci->focus->cx >= 0 && strchr(mode, ':')) {
-               /* We want a cursor */
-               cx = x + ci->focus->cx;
-               cy = y + ci->focus->cy;
-       }
-       for (i = 0; i < h; i+= 2) {
-               static const wint_t hilo = 0x2580; /* L'▀' */
-               for (j = 0; j < w ; j+= 1) {
-                       unsigned char *p1 = buf + i*w*4 + j*4;
-                       unsigned char *p2 = buf + (i+1)*w*4 + j*4;
-                       int rgb1[3] = { p1[0]*1000/255, p1[1]*1000/255, p1[2]*1000/255 };
-                       int rgb2[3] = { p2[0]*1000/255, p2[1]*1000/255, p2[2]*1000/255 };
-                       int fg = find_col(dd, rgb1);
-                       int bg = find_col(dd, rgb2);
-
-                       if (p1[3] < 128 || p2[3] < 128) {
-                               /* transparent */
-                               cchar_t cc;
-                               short f,b;
-                               struct pane *pn2 = ci->focus;
-                               PANEL *pan = pane_panel(pn2, NULL);
-
-                               while (!pan && pn2->parent != pn2) {
-                                       pn2 = pn2->parent;
-                                       pan = pane_panel(pn2, NULL);
-                               }
-                               if (pan) {
-                                       wgetbkgrnd(panel_window(pan), &cc);
-                                       if (cc.ext_color == 0)
-                                               /* default.  This is light
-                                                * gray rather then white,
-                                                * but I think it is a good
-                                                * result.
-                                                */
-                                               b = COLOR_WHITE;
-                                       else
-                                               pair_content(cc.ext_color, &f, &b);
-                                       if (p1[3] < 128)
-                                               fg = b;
-                                       if (p2[3] < 128)
-                                               bg = b;
-                               }
-                       }
-                       /* FIXME this doesn't work because
-                        * render-line knows too much and gets it wrong.
-                        */
-                       if (cx == x+j && cy == y + (i/2))
-                               ncurses_text(ci->focus, p, 'X', 0,
-                                            to_pair(dd, 0, 0),
-                                            x+j, y+(i/2), 1);
-                       else
-                               ncurses_text(ci->focus, p, hilo, 0,
-                                            to_pair(dd, fg, bg),
-                                            x+j, y+(i/2), 0);
-
-               }
-       }
-       free(buf);
+       dii.c = nc_draw_image_cb;
+       dii.wd = wd;
+       dii.p = p;
+       dii.w = dii.h = dii.x = dii.y = dii.xo = dii.yo = 0;
+       call("Draw:scale-image", ci->focus,
+            ci->num, NULL, NULL, ci->num2, NULL, ci->str2,
+            ci->x, ci->y, &dii.c);
 
        DestroyMagickWand(wd);
 
index e9cb956055440dc0c3844da228833ed4f9d6bd57..a006c94569883bff5babf3cc2943c60d71481920 100644 (file)
@@ -805,59 +805,102 @@ DEF_CMD(xcb_draw_text)
        return 1;
 }
 
+struct di_info {
+       struct command c;
+       MagickWand *wd safe;
+       int x,y,w,h;
+       int xo, yo;
+       struct panes *ps safe;
+};
+
+DEF_CB(xcb_draw_image_cb)
+{
+       struct di_info *dii = container_of(ci->comm, struct di_info, c);
+       int stride;
+       int fmt[2];
+       unsigned char *buf;
+       cairo_surface_t *surface;
+
+       switch (ci->key[0]) {
+       case 'w': /* width */
+               return MagickGetImageWidth(dii->wd);
+       case 'h': /* height */
+               return MagickGetImageHeight(dii->wd);
+       case 's': /* scale */
+               MagickAdaptiveResizeImage(dii->wd, ci->num, ci->num2);
+               return 1;
+       case 'c': /* crop or cursor */
+               if (ci->key[1] != 'u') {
+                       /* crop */
+                       dii->x = ci->x;
+                       dii->y = ci->y;
+                       dii->w = ci->num;
+                       dii->h = ci->num2;
+                       return 1;
+               } else {
+                       /* cursor */
+                       cairo_rectangle(dii->ps->ctx,
+                                       ci->x + dii->xo, ci->y + dii->yo,
+                                       ci->num, ci->num2);
+                       cairo_set_line_width(dii->ps->ctx, 1.0);
+                       cairo_set_source_rgb(dii->ps->ctx, 1.0, 0.0, 0.0);
+                       cairo_stroke(dii->ps->ctx);
+                       return 1;
+               }
+       case 'd': /* draw */
+               if (dii->w <= 0 || dii->h <= 0)
+                       return Efail;
+               stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
+                                                      dii->w);
+               buf = malloc(dii->h * stride);
+               // Cairo expects 32bit values with A in the high byte, then RGB.
+               // Magick provides 8bit values in the order requests.
+               // So depending on byte order, a different string is needed
+
+               fmt[0] = ('A'<<24) | ('R' << 16) | ('G' << 8) | ('B' << 0);
+               fmt[1] = 0;
+               MagickExportImagePixels(dii->wd, dii->x, dii->y,
+                                       dii->w, dii->h,
+                                       (char*)fmt, CharPixel, buf);
+               surface = cairo_image_surface_create_for_data(
+                       buf, CAIRO_FORMAT_ARGB32, dii->w, dii->h, stride);
+               cairo_set_source_surface(dii->ps->ctx, surface,
+                                        ci->num + dii->xo, ci->num2 + dii->yo);
+               cairo_paint(dii->ps->ctx);
+               cairo_surface_destroy(surface);
+               free(buf);
+               return 1;
+       default:
+               return Efail;
+       }
+}
+
 DEF_CMD(xcb_draw_image)
 {
        /* 'str' identifies the image. Options are:
         *     file:filename  - load file from fs
         *     comm:command   - run command collecting bytes
-        * 'str2' container 'mode' information.
-        *     By default the image is placed centrally in the pane
-        *     and scaled to use either fully height or fully width.
-        *     Various letters modify this:
-        *     'S' - stretch to use full height *and* full width
-        *     'L' - place on left if full width isn't used
-        *     'R' - place on right if full width isn't used
-        *     'T' - place at top if full height isn't used
-        *     'B' - place at bottom if full height isn't used.
-        *
-        *    Also a suffix ":NNxNN" will be parse and the two numbers used
-        *    to give number of rows and cols to overlay on the image for
-        *    the purpose of cursor positioning.  If these are present and
-        *    p->cx,cy are not negative, draw a cursor at p->cx,cy highlighting
-        *    the relevant cell.
-        *
-        * num,num2, if both positive, override the automatic scaling.
-        *    The image is scaled to this many pixels.
-        * x,y is top-left pixel in the scaled image to start display at.
-        *    Negative values allow a margin between pane edge and this image.
+        * 'str2' and numbers are handled by Draw:scale-image.
         */
        struct xcb_data *xd = ci->home->data;
-       const char *mode = ci->str2 ?: "";
-       bool stretch = strchr(mode, 'S');
-       int w, h;
-       int x = 0, y = 0;
-       int pw, ph;
-       int xo, yo;
-       int cix, ciy;
-       int stride;
+       struct di_info dii;
+       MagickWand *wd = NULL;
        struct panes *ps;
-       MagickBooleanType status;
-       MagickWand *wd;
-       int fmt[2];
-       unsigned char *buf;
-       cairo_surface_t *surface;
 
        if (!ci->str)
                return Enoarg;
-       ps = find_pixmap(xd, ci->focus, &xo, &yo);
+       ps = find_pixmap(xd, ci->focus, &dii.xo, &dii.yo);
        if (!ps)
                return Einval;
-       if (!ps->ctx)
-               instantiate_pixmap(xd, ps);
-       ps->bg.g = -1;
-       if (!ps->ctx)
+       dii.ps = ps;
+       if (!dii.ps->ctx)
+               instantiate_pixmap(xd, dii.ps);
+       dii.ps->bg.g = -1;
+       if (!dii.ps->ctx)
                return Efail;
        if (strstarts(ci->str, "file:")) {
+               MagickBooleanType status;
+
                wd = NewMagickWand();
                status = MagickReadImage(wd, ci->str + 5);
                if (status == MagickFalse) {
@@ -865,7 +908,9 @@ DEF_CMD(xcb_draw_image)
                        return Efail;
                }
        } else if (strstarts(ci->str, "comm:")) {
+               MagickBooleanType status;
                struct call_return cr;
+
                wd = NewMagickWand();
                cr = call_ret(bytes, ci->str+5, ci->focus);
                if (!cr.s) {
@@ -878,106 +923,19 @@ DEF_CMD(xcb_draw_image)
                        DestroyMagickWand(wd);
                        return Efail;
                }
-       } else
+       }
+
+       if (!wd)
                return Einval;
 
        MagickAutoOrientImage(wd);
-       w = ci->focus->w;
-       h = ci->focus->h;
-       if (ci->num > 0 && ci->num2 > 0) {
-               w = ci->num;
-               h = ci->num2;
-       } else if (ci->num > 0) {
-               int ih = MagickGetImageHeight(wd);
-               int iw = MagickGetImageWidth(wd);
-
-               if (iw <= 0 || iw <= 0) {
-                       DestroyMagickWand(wd);
-                       return Efail;
-               }
-               w = iw * ci->num / 1024;
-               h = ih * ci->num / 1024;
-       } else if (!stretch) {
-               int ih = MagickGetImageHeight(wd);
-               int iw = MagickGetImageWidth(wd);
-
-               if (iw <= 0 || iw <= 0) {
-                       DestroyMagickWand(wd);
-                       return Efail;
-               }
-               if (iw * h > ih * w) {
-                       /* Image is wider than space, use less height */
-                       ih = ih * w / iw;
-                       if (strchr(mode, 'B'))
-                               /* bottom */
-                               y = h - ih;
-                       else if (!strchr(mode, 'T'))
-                               /* center */
-                               y = (h - ih) / 2;
-                       h = ih;
-               } else {
-                       /* image is too tall, use less width */
-                       iw = iw * h / ih;
-                       if (strchr(mode, 'R'))
-                               /* right */
-                               x = w - iw;
-                       else if (!strchr(mode, 'L'))
-                               x = (w - iw) / 2;
-                       w = iw;
-               }
-       }
-       MagickAdaptiveResizeImage(wd, w, h);
-       pw = ci->focus->w;
-       ph = ci->focus->h;
-       cix = ci->x;
-       ciy = ci->y;
-       if (cix < 0) {
-               xo -= cix;
-               pw += cix;
-               cix = 0;
-       }
-       if (ciy < 0) {
-               yo -= ciy;
-               ph += ciy;
-               ciy = 0;
-       }
-       if (w - cix <= pw)
-               w -= cix;
-       else
-               w = pw;
-       if (h - ciy <= ph)
-               h -= ciy;
-       else
-               h = ph;
-       stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
-       buf = malloc(h * stride);
-       // Cairo expects 32bit values with A in the high byte, then RGB.
-       // Magick provides 8bit values in the order requests.
-       // So depending on byte order, a different string is needed
+       dii.c = xcb_draw_image_cb;
+       dii.wd = wd;
+       dii.w = dii.h = dii.x = dii.y = dii.xo = dii.yo = 0;
+       call("Draw:scale-image", ci->focus,
+            ci->num, NULL, NULL, ci->num2, NULL, ci->str2,
+            ci->x, ci->y, &dii.c);
 
-       fmt[0] = ('A'<<24) | ('R' << 16) | ('G' << 8) | ('B' << 0);
-       fmt[1] = 0;
-       MagickExportImagePixels(wd, cix, ciy, w, h,
-                               (char*)fmt, CharPixel, buf);
-       surface = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32,
-                                                     w, h, stride);
-       cairo_set_source_surface(ps->ctx, surface, x + xo, y + yo);
-       cairo_paint(ps->ctx);
-       cairo_surface_destroy(surface);
-       free(buf);
-
-       if (ci->focus->cx >= 0) {
-               struct pane *p = ci->focus;
-               int rows, cols;
-               char *cl = strchr(mode, ':');
-               if (cl && sscanf(cl, ":%dx%d", &cols, &rows) == 2) {
-                       cairo_rectangle(ps->ctx, p->cx + xo, p->cy + yo,
-                                       w/cols, h/rows);
-                       cairo_set_line_width(ps->ctx, 1.0);
-                       cairo_set_source_rgb(ps->ctx, 1.0, 0.0, 0.0);
-                       cairo_stroke(ps->ctx);
-               }
-       }
        DestroyMagickWand(wd);
 
        pane_damaged(ci->home, DAMAGED_POSTORDER);
index f3dbc6c2332a162c060fbdf44a2b139db773f616..150ede91df72da78650af87e967baf2bd05894a1 100644 (file)
@@ -130,41 +130,41 @@ Display 80,30 32AAA2452953CA412B6C501C049F17A9 41,0
 Key ":C-V"
 Display 80,30 EDAF305E1201F1CEA222CE692A096833 41,14
 Key ":C-V"
-Display 80,30 50443615B49D117F5C027319CFA89B1E 41,23
+Display 80,30 24B378D77925D238A39E20FF8409DC58 41,23
 Key ":C-V"
 Display 80,30 A9C2CE554971E61FCCBA577E0FAA2E51 41,23
 Key ":C-V"
-Display 80,30 B7BD5F8F519A164138FC3A744E87995B 41,19
+Display 80,30 80BFE9BD891136C6DA2F6E86C634C7A6 41,19
 Key ":C-V"
-Display 80,30 89F3E4969386562A4541DFE03E746047 41,25
+Display 80,30 5A34BD9963F7220D335814D0CF4CF6F0 41,25
 Key ":C-V"
-Display 80,30 8ECD5B33AD931522FD8942DD21B4DBBF 41,19
+Display 80,30 CD6FDF42EA8E3F33F2C724ABFE29BCD9 41,19
 Key ":C-V"
-Display 80,30 D98DD7B91EEEF2D35EAD485D2252054D 41,25
+Display 80,30 44B8E6837CEE52F8B5A39204CC7A0EA8 41,25
 Key ":C-V"
-Display 80,30 B825A7DE11DA8606F70EE48A96B8C89D 41,22
+Display 80,30 A10016532503907B42F429D381E2D554 41,22
 Key ":C-V"
-Display 80,30 EEF0EC05C62400521394262146B15B62 41,20
+Display 80,30 0F2D596198D3188EED67E6B0EFF4E860 41,20
 Key ":C-V"
-Display 80,30 C12CD388ED436FAB7AA25E6BD10EE7C9 41,27
+Display 80,30 9994CA0D1995DEB50903586F8911FEC3 41,27
 Key ":A-v"
-Display 80,30 57309EC1307757082E9DD0962C044601 41,19
+Display 80,30 A92659CC1C8F76FF3D7838FEC045B638 41,19
 Key ":A-v"
-Display 80,30 42C17C0D79F95153E760C3C7051E99B7 41,4
+Display 80,30 079832D06081B6AFAA6C1A50B088A02A 41,4
 Key ":A-v"
-Display 80,30 556C798DC3E58F49718F72B31CC43CCE 41,2
+Display 80,30 65A04A615A574E7A7D9CC550E20DC769 41,2
 Key ":A-v"
-Display 80,30 925B1518F50375FC3A53CF199F0763B3 41,5
+Display 80,30 308C19E289DE5E8F094FAB37B4D80861 41,5
 Key ":C-X"
-Display 80,30 C77A763803918CD43C14DE9BBC75FE7B 41,5
+Display 80,30 FA340030449E00D248815C79F8A5CA8C 41,5
 Key "-o"
-Display 80,30 925B1518F50375FC3A53CF199F0763B3 41,5
+Display 80,30 308C19E289DE5E8F094FAB37B4D80861 41,5
 Key "- "
-Display 80,30 8DE5E802C5FB540C1108886EEE7BD387 41,5
+Display 80,30 EF77D170B48154461AB517006E36C128 41,5
 Key "- "
 Display 80,30 D05FA5555E5753EF7C63130BFCC5F298 41,5
 Key ":Backspace"
-Display 80,30 95609A412E56BB1A19FB84AA753E62B8 41,5
+Display 80,30 18512898A7A2054C3E506AA0412A8871 41,5
 Key ":Backspace"
 Display 80,30 EB57713F78EB85789B0CAE8B35B59A6D 41,5
 Key ":C-X"
@@ -176,33 +176,33 @@ Display 80,30 FA86716DAC8F2E24B38E71C82185A6F6 41,0
 Key ":C-V"
 Display 80,30 E95B1E8C501DBCB5CD04B4D94417CFE7 41,14
 Key ":C-V"
-Display 80,30 9A5DD296215402CC74D1D720F3F820F1 41,23
+Display 80,30 493C5A6D6986B8FF8616ACA771B1F12B 41,23
 Key ":C-S"
-Display 80,30 2097376AE950E385F190D8101FBDD47F 70,0
+Display 80,30 F0633C4ED34235C5B1D1B2AF0795ECE4 70,0
 Key "-e"
-Display 80,30 83ADA35DA249CA84904FD93978F13D88 71,0
-Display 80,30 9D6D90E19DFE188EBBE2DE863915312E 71,0
+Display 80,30 93F4C2ED181D80340B035CABA8C22F47 71,0
+Display 80,30 4EF4BFB068CFD0B574F4B469CD1F8804 71,0
 Key "-m"
-Display 80,30 F1B3D5B1AA800B752C37CCA8405B2095 72,0
+Display 80,30 FD535E0CA62186FE60D9791A859A3866 72,0
 Key "-p"
-Display 80,30 8045670F17ED3F441937988AA15F7548 73,0
-Display 80,30 EE2BB6009BBB06973E87D16C2F101F3F 73,0
+Display 80,30 41C3E4217288B4D8D4EC07031CC74AE5 73,0
+Display 80,30 A0E51F3255FA21B7ECE798CFEACD4960 73,0
 Key ":Enter"
-Display 80,30 7DB9F15A949DA58D7B427E7E38DABFC6 52,13
+Display 80,30 E80738A12817CC5CFDC4A1BFD34D8B2D 52,13
 Key ":C-L"
-Display 80,30 3F073FF1DC666B464A9F7A4BEB29E344 52,13
+Display 80,30 F683653F333FB5995F3F06E1973434BD 52,13
 Key ":C-S"
-Display 80,30 F446ED1B62EAB70A53390B79F6B917CD 70,0
+Display 80,30 BE6AA179DA2B5B277A025D8B15FC34B0 70,0
 Key ":C-S"
-Display 80,30 13E0C7059235BBCFCDFD055B29F062FD 73,0
-Display 80,30 7488B884D954DE9E856D7BCB50A5DF57 73,0
+Display 80,30 AFFACF34F3D48EEBE73A69FA87D24D5D 73,0
+Display 80,30 0D7BAB2BC9AF139F12C0CC87DB1F27AD 73,0
 Key ":C-S"
-Display 80,30 7752BD089F25A386DDE9926C81C71780 72,0
-Display 80,30 63BE4545AE7FF2A764814913C8CF31E2 72,0
+Display 80,30 A7A665D627FDC7D40FD3874DB5D9243D 72,0
+Display 80,30 D18D81F1F64602644D0A38A1767923D4 72,0
 Key ":Enter"
-Display 80,30 D60957D735072E7A20705B01CE156B1D 52,21
+Display 80,30 60607FF8A4916C216A7EB7739678B955 52,21
 Key ":C-V"
-Display 80,30 01D13EAA75BA12602218BB9F0B802907 41,25
+Display 80,30 5E2E4C433D958D3FCD42B6071B24E6B4 41,25
 Key ":C-V"
 Display 80,30 90A6DF6667023AAFC1FC320CE20C1851 41,20
 Key ":A->"