From e1969beea284022ab721b452a43736b49cf74ce3 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Mon, 10 Dec 2018 19:43:08 +0000 Subject: [PATCH] Scaling PoC --- lisp/image.el | 2 -- src/dispextern.h | 7 +++++++ src/image.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ src/nsimage.m | 2 +- src/nsterm.m | 7 ++++--- src/xterm.c | 48 +++++++++++++++++++++++++++++++++++++-------- 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/lisp/image.el b/lisp/image.el index 74a23046e9..8989fceefd 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -982,8 +982,6 @@ image--get-image image)) (defun image--get-imagemagick-and-warn () - (unless (or (fboundp 'imagemagick-types) (featurep 'ns)) - (error "Cannot rescale images without ImageMagick support")) (let ((image (image--get-image))) (image-flush image) (when (fboundp 'imagemagick-types) diff --git a/src/dispextern.h b/src/dispextern.h index 4cd017603d..490cc10c6c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2987,6 +2987,13 @@ struct image /* Width and height of the image. */ int width, height; + /* Width and height of the image data. */ + int actual_width, actual_height; + + /* The scaling factor between the actual image data and the + output. */ + double scale; + /* These values are used for the rectangles displayed for images that can't be loaded. */ #define DEFAULT_IMAGE_WIDTH 30 diff --git a/src/image.c b/src/image.c index 633d66e7a7..8bda88a6ce 100644 --- a/src/image.c +++ b/src/image.c @@ -1748,6 +1748,55 @@ postprocess_image (struct frame *f, struct image *img) } +static void +set_image_size (struct image *img, Lisp_Object spec) +{ + Lisp_Object value; + int width = INT_MAX, height = INT_MAX; + double scale = 1; + + img->actual_width = img->width; + img->actual_height = img->height; + + value = image_spec_value (spec, QCscale, NULL); + if (NUMBERP (value)) + scale = XFLOATINT (value); + + /* Calculate the maximum width and height. */ + value = image_spec_value (spec, QCmax_width, NULL); + if (FIXNATP (value)) + width = XFIXNAT (value); + + value = image_spec_value (spec, QCmax_height, NULL); + if (FIXNATP (value)) + height = XFIXNAT (value); + + value = image_spec_value (spec, QCwidth, NULL); + if (FIXNATP (value)) + width = min (XFIXNAT (value) * scale, width); + + value = image_spec_value (spec, QCheight, NULL); + if (FIXNATP (value)) + height = min (XFIXNAT (value) * scale, height); + + /* Calculate the final scaling factor. */ + if (img->width * scale > width) + scale = (double) img->width / width; + + if (img->height * scale > height) + scale = (double) img->height / height; + + /* Set the final sizes. We always maintain the aspect ratio. */ + if (scale != 1) + { + img->width *= scale; + img->height *= scale; + } + + img->scale = scale; +} + + /* Return the id of image with Lisp specification SPEC on frame F. SPEC must be a valid Lisp image specification (see valid_image_p). */ @@ -1803,6 +1852,8 @@ lookup_image (struct frame *f, Lisp_Object spec) Lisp_Object ascent, margin, relief, bg; int relief_bound; + set_image_size (img, spec); + ascent = image_spec_value (spec, QCascent, NULL); if (FIXNUMP (ascent)) img->ascent = XFIXNAT (ascent); diff --git a/src/nsimage.m b/src/nsimage.m index 0ae1b88edd..cc3aceae69 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -126,7 +126,7 @@ Updated by Christian Limpach (chris@nice.ch) eImg = temp; } - [eImg setSizeFromSpec:XCDR (img->spec)]; + //[eImg setSizeFromSpec:XCDR (img->spec)]; size = [eImg size]; img->width = size.width; diff --git a/src/nsterm.m b/src/nsterm.m index 6c285f0abb..db357a9623 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3828,6 +3828,7 @@ Function modeled after x_draw_glyph_string_box (). NSRect br; struct face *face; NSColor *tdCol; + double scale = s->img->scale; NSTRACE ("ns_dumpglyphs_image"); @@ -3877,9 +3878,9 @@ Function modeled after x_draw_glyph_string_box (). { #ifdef NS_IMPL_COCOA NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height); - NSRect ir = NSMakeRect (s->slice.x, - s->img->height - s->slice.y - s->slice.height, - s->slice.width, s->slice.height); + NSRect ir = NSMakeRect (s->slice.x / scale, + (s->img->height - s->slice.y - s->slice.height) / scale, + s->slice.width / scale , s->slice.height / scale); [img drawInRect: dr fromRect: ir operation: NSCompositingOperationSourceOver diff --git a/src/xterm.c b/src/xterm.c index 3a7e31e712..f3d0af4177 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -136,6 +136,9 @@ along with GNU Emacs. If not, see . */ #include #endif +#include +#include + /* Default to using XIM if available. */ #ifdef USE_XIM bool use_xim = true; @@ -2970,6 +2973,39 @@ x_draw_glyph_string_box (struct glyph_string *s) } +static void +x_composite_image (struct glyph_string *s, Pixmap dest, + int srcX, int srcY, int dstX, int dstY, + int width, int height) +{ + Picture source, destination; + XRenderPictFormat *default_format, *source_format; + XRenderPictureAttributes source_attr, dest_attr; + + double scale = s->img->scale; + XTransform tmat = {{{XDoubleToFixed (1), XDoubleToFixed (0), XDoubleToFixed (0)}, + {XDoubleToFixed (0), XDoubleToFixed (1), XDoubleToFixed (0)}, + {XDoubleToFixed (0), XDoubleToFixed (0), XDoubleToFixed (scale)}}}; + + default_format = XRenderFindVisualFormat (s->display, DefaultVisual (s->display, 0)); + source_format = XRenderFindStandardFormat (s->display, PictStandardRGB24); + + source = XRenderCreatePicture (s->display, s->img->pixmap, source_format, 0, &source_attr); + destination = XRenderCreatePicture (s->display, dest, default_format, 0, &dest_attr); + + XRenderSetPictureTransform (s->display, source, &tmat); + + XRenderComposite (s->display, PictOpOver, source, None, destination, + srcX*scale, srcY*scale, + 0, 0, + dstX, dstY, + width, height); + + XRenderFreePicture (s->display, source); + XRenderFreePicture (s->display, destination); +} + + /* Draw foreground of image glyph string S. */ static void @@ -3018,10 +3054,8 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) - XCopyArea (s->display, s->img->pixmap, - FRAME_X_DRAWABLE (s->f), s->gc, - s->slice.x + r.x - x, s->slice.y + r.y - y, - r.width, r.height, r.x, r.y); + x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + r.x, r.y, r.width, r.height); } else { @@ -3033,10 +3067,8 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) - XCopyArea (s->display, s->img->pixmap, - FRAME_X_DRAWABLE (s->f), s->gc, - s->slice.x + r.x - x, s->slice.y + r.y - y, - r.width, r.height, r.x, r.y); + x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + r.x, r.y, r.width, r.height); /* When the image has a mask, we can expect that at least part of a mouse highlight or a block cursor will -- 2.19.1