]> git.eshelyaron.com Git - emacs.git/commitdiff
Support native image resizing on MS-Windows
authorEli Zaretskii <eliz@gnu.org>
Sun, 20 Jan 2019 15:59:12 +0000 (17:59 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sun, 20 Jan 2019 15:59:12 +0000 (17:59 +0200)
* src/w32term.c (x_draw_image_foreground): Scale the image if
the requested dimensions are different from the bitmap
dimensions.
* src/image.c (Fimage_scaling_p): Return t when HAVE_NTGUI.
(x_set_image_size) [HAVE_NTGUI]: Record the scaled dimensions
in the image struct.
* src/dispextern.h (HAVE_NATIVE_SCALING): Define when
HAVE_NTGUI as well.

* etc/NEWS: Update the announcement of native image scaling.

etc/NEWS
src/dispextern.h
src/image.c
src/w32term.c

index 9d91a30a5832827e4ce64c79b29bb092b4b7779c..21187474a288b327ef86ea4702ccaddda36ba32d 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1505,8 +1505,12 @@ buffer's 'default-directory' and invoke that file name handler to make
 the process.  That way 'make-process' can start remote processes.
 
 +++
-** Emacs now supports resizing images without ImageMagick on X window
-systems where the XRender extension is available, and on the NS port.
+** Emacs now supports resizing (scaling) of images without ImageMagick.
+All modern systems are supported by this feature.  (On GNU and Unix
+systems, the XRender extension to X11 is required for this to be
+available; the configure script will test for it and, if found, enable
+scaling.)
+
 The new function 'image-scaling-p' can be used to test whether any
 given frame supports resizing.
 
index 9cea3218c161e8abba805623c9736dde4a84cc4b..894753669d05e73de1837ba965673d6ecb918532 100644 (file)
@@ -2938,7 +2938,7 @@ struct redisplay_interface
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-# if defined HAVE_XRENDER || defined HAVE_NS
+# if defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_NTGUI
 #  define HAVE_NATIVE_SCALING
 # endif
 
index bcc61dfccdab25a5cacf6a7fece3aa8a7d239217..20148605817777a791f69a2a65b18ef35741524c 100644 (file)
@@ -1900,6 +1900,12 @@ x_set_image_size (struct frame *f, struct image *img)
       img->height = height;
     }
 # endif
+# ifdef HAVE_NTGUI
+  /* Under HAVE_NTGUI, we will scale the image on the fly, when we
+     draw it.  See w32term.c:x_draw_image_foreground.  */
+  img->width = width;
+  img->height = height;
+# endif
 #endif
 }
 
@@ -9915,7 +9921,7 @@ DEFUN ("image-scaling-p", Fimage_scaling_p, Simage_scaling_p, 0, 1, 0,
 Return t if FRAME supports native scaling, nil otherwise.  */)
      (Lisp_Object frame)
 {
-#ifdef HAVE_NS
+#if defined (HAVE_NS) || defined (HAVE_NTGUI)
   return Qt;
 #elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER)
   int event_basep, error_basep;
index d13763d7db37c37083a0644cb2649b1ff70bda03..6fc86124199d37ab3b18c36d8fbb978ea09f6555 100644 (file)
@@ -1874,9 +1874,24 @@ x_draw_image_foreground (struct glyph_string *s)
       HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
       HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
       HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+      LONG orig_width, orig_height;
+      DIBSECTION dib;
       SetBkColor (compat_hdc, RGB (255, 255, 255));
       SetTextColor (s->hdc, RGB (0, 0, 0));
       x_set_glyph_string_clipping (s);
+      /* Extract the original dimensions of the bitmap.  */
+      if (GetObject (s->img->pixmap, sizeof (dib), &dib) > 0)
+       {
+         BITMAP bmp = dib.dsBm;
+         orig_width = bmp.bmWidth;
+         orig_height = bmp.bmHeight;
+       }
+      else
+       {
+         DebPrint (("x_draw_image_foreground: GetObject failed!\n"));
+         orig_width = s->slice.width;
+         orig_height = s->slice.height;
+       }
 
       if (s->img->mask)
        {
@@ -1885,14 +1900,36 @@ x_draw_image_foreground (struct glyph_string *s)
 
          SetTextColor (s->hdc, RGB (255, 255, 255));
          SetBkColor (s->hdc, RGB (0, 0, 0));
-
-         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
-                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
-         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
-                 mask_dc, s->slice.x, s->slice.y, SRCAND);
-         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
-                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
-
+         if (s->slice.width == orig_width && s->slice.height == orig_height)
+           {
+             BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                     compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+             BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                     mask_dc, s->slice.x, s->slice.y, SRCAND);
+             BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                     compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+           }
+         else
+           {
+             int pmode = 0;
+             /* HALFTONE produces better results, especially when
+                scaling to a larger size, but Windows 9X doesn't
+                support HALFTONE.  */
+             if (os_subtype == OS_NT
+                 && (pmode = SetStretchBltMode (s->hdc, HALFTONE)) != 0)
+               SetBrushOrgEx (s->hdc, 0, 0, NULL);
+             StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                         compat_hdc, s->slice.x, s->slice.y,
+                         orig_width, orig_height, SRCINVERT);
+             StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                         mask_dc, s->slice.x, s->slice.y,
+                         orig_width, orig_height, SRCAND);
+             StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                         compat_hdc, s->slice.x, s->slice.y,
+                         orig_width, orig_height, SRCINVERT);
+             if (pmode)
+               SetStretchBltMode (s->hdc, pmode);
+           }
          SelectObject (mask_dc, mask_orig_obj);
          DeleteDC (mask_dc);
        }
@@ -1900,9 +1937,22 @@ x_draw_image_foreground (struct glyph_string *s)
        {
          SetTextColor (s->hdc, s->gc->foreground);
          SetBkColor (s->hdc, s->gc->background);
-
-          BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
-                  compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
+         if (s->slice.width == orig_width && s->slice.height == orig_height)
+           BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                   compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
+         else
+           {
+             int pmode = 0;
+             /* Windows 9X doesn't support HALFTONE.  */
+             if (os_subtype == OS_NT
+                 && (pmode = SetStretchBltMode (s->hdc, HALFTONE)) != 0)
+               SetBrushOrgEx (s->hdc, 0, 0, NULL);
+             StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                         compat_hdc, s->slice.x, s->slice.y,
+                         orig_width, orig_height, SRCCOPY);
+             if (pmode)
+               SetStretchBltMode (s->hdc, pmode);
+           }
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2031,6 +2081,10 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
   if (s->slice.y == 0)
     y += s->img->vmargin;
 
+  /* FIXME (maybe): The below doesn't support image scaling.  But it
+     seems to never be called, because the conditions for its call in
+     x_draw_image_glyph_string are never fulfilled (they will be if
+     the #ifdef'ed away part of that function is ever activated).  */
   if (s->img->pixmap)
     {
       HDC compat_hdc = CreateCompatibleDC (hdc);