Support native image resizing on MS-Windows

* 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.
This commit is contained in:
Eli Zaretskii 2019-01-20 17:59:12 +02:00
parent 551051596f
commit 67b1053dcd
4 changed files with 79 additions and 15 deletions

View file

@ -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.

View 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

View 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;

View 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);