aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCecilio Pardo2024-11-04 18:58:40 +0100
committerEli Zaretskii2024-11-05 14:37:07 +0200
commit4e8bf2977e6d1abf6d3cf82e9c1ae3dee5bfcda0 (patch)
treec52d029ee9f13d91f075bf2b34d0380274955d84 /src
parent8a7910fb67e3b89de430d3b3e5009b145ec0c602 (diff)
downloademacs-4e8bf2977e6d1abf6d3cf82e9c1ae3dee5bfcda0.tar.gz
emacs-4e8bf2977e6d1abf6d3cf82e9c1ae3dee5bfcda0.zip
Support :transform-smoothing on images (MS-Windows) (bug#57166)
* src/dispextern.h (struct image): Add field 'smoothing' for NTGUI. * src/image.c (image_set_transform): Assign the 'smoothing' field of the image struct. * src/w32gdiplus.h: Add references to more GDI+ functions. * src/w32image.c (gdiplus_init): Add references to more GDI+ functions. * src/w32term.c (w32_draw_image_foreground): If the image is marked for smoothing and GDI+ is available, draw it with GDI+ bilinear interpolation. * etc/NEWS: New entry for this change.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h1
-rw-r--r--src/image.c10
-rw-r--r--src/w32gdiplus.h27
-rw-r--r--src/w32image.c25
-rw-r--r--src/w32term.c60
5 files changed, 109 insertions, 14 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index cc248a4472e..004eb82d87a 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3172,6 +3172,7 @@ struct image
3172#endif /* HAVE_ANDROID */ 3172#endif /* HAVE_ANDROID */
3173#ifdef HAVE_NTGUI 3173#ifdef HAVE_NTGUI
3174 XFORM xform; 3174 XFORM xform;
3175 bool smoothing;
3175#endif 3176#endif
3176#ifdef HAVE_HAIKU 3177#ifdef HAVE_HAIKU
3177 /* The affine transformation to apply to this image. */ 3178 /* The affine transformation to apply to this image. */
diff --git a/src/image.c b/src/image.c
index 34936977a40..db7f6acd171 100644
--- a/src/image.c
+++ b/src/image.c
@@ -3049,12 +3049,10 @@ image_set_transform (struct frame *f, struct image *img)
3049 flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); 3049 flip = !NILP (image_spec_value (img->spec, QCflip, NULL));
3050 3050
3051# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU \ 3051# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU \
3052 || defined HAVE_ANDROID 3052 || defined HAVE_ANDROID || defined HAVE_NTGUI
3053 /* We want scale up operations to use a nearest neighbor filter to 3053 /* We want scale up operations to use a nearest neighbor filter to
3054 show real pixels instead of munging them, but scale down 3054 show real pixels instead of munging them, but scale down
3055 operations to use a blended filter, to avoid aliasing and the like. 3055 operations to use a blended filter, to avoid aliasing and the like. */
3056
3057 TODO: implement for Windows. */
3058 bool smoothing; 3056 bool smoothing;
3059 Lisp_Object s = image_spec_value (img->spec, QCtransform_smoothing, NULL); 3057 Lisp_Object s = image_spec_value (img->spec, QCtransform_smoothing, NULL);
3060 if (NILP (s)) 3058 if (NILP (s))
@@ -3067,6 +3065,10 @@ image_set_transform (struct frame *f, struct image *img)
3067 img->use_bilinear_filtering = smoothing; 3065 img->use_bilinear_filtering = smoothing;
3068#endif 3066#endif
3069 3067
3068#ifdef HAVE_NTGUI
3069 img->smoothing = smoothing;
3070#endif
3071
3070 /* Perform scale transformation. */ 3072 /* Perform scale transformation. */
3071 3073
3072 matrix3x3 matrix 3074 matrix3x3 matrix
diff --git a/src/w32gdiplus.h b/src/w32gdiplus.h
index 9d05ae6c190..b438b1a64f8 100644
--- a/src/w32gdiplus.h
+++ b/src/w32gdiplus.h
@@ -2,6 +2,9 @@
2typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc) 2typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc)
3 (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *); 3 (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *);
4typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR); 4typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR);
5typedef GpStatus (WINGDIPAPI *GdipCreateFromHDC_Proc)
6 (HDC hdc, GpGraphics **graphics);
7typedef GpStatus (WINGDIPAPI *GdipDeleteGraphics_Proc) (GpGraphics *graphics);
5typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc) 8typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc)
6 (GpImage *, PROPID, UINT *); 9 (GpImage *, PROPID, UINT *);
7typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc) 10typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc)
@@ -20,6 +23,15 @@ typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc)
20 (IStream *, GpBitmap **); 23 (IStream *, GpBitmap **);
21typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromScan0_Proc) 24typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromScan0_Proc)
22 (INT, INT, INT, PixelFormat, BYTE*, GpBitmap**); 25 (INT, INT, INT, PixelFormat, BYTE*, GpBitmap**);
26typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromHBITMAP_Proc)
27 (HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap);
28typedef GpStatus (WINGDIPAPI *GdipSetInterpolationMode_Proc)
29 (GpGraphics *graphics, InterpolationMode interpolationMode);
30typedef GpStatus (WINGDIPAPI *GdipDrawImageRectRectI_Proc)
31 (GpGraphics *graphics, GpImage *image, INT dstx, INT dsty, INT dstwidth,
32 INT dstheight, INT srcx, INT srcy, INT srcwidth, INT srcheight,
33 GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
34 DrawImageAbort callback, VOID * callbackData);
23typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT); 35typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT);
24typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc) 36typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc)
25 (GpBitmap *, HBITMAP *, ARGB); 37 (GpBitmap *, HBITMAP *, ARGB);
@@ -41,6 +53,8 @@ typedef GpStatus (WINGDIPAPI *GdipImageRotateFlip_Proc)
41 53
42extern GdiplusStartup_Proc fn_GdiplusStartup; 54extern GdiplusStartup_Proc fn_GdiplusStartup;
43extern GdiplusShutdown_Proc fn_GdiplusShutdown; 55extern GdiplusShutdown_Proc fn_GdiplusShutdown;
56extern GdipCreateFromHDC_Proc fn_GdipCreateFromHDC;
57extern GdipDeleteGraphics_Proc fn_GdipDeleteGraphics;
44extern GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize; 58extern GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
45extern GdipGetPropertyItem_Proc fn_GdipGetPropertyItem; 59extern GdipGetPropertyItem_Proc fn_GdipGetPropertyItem;
46extern GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount; 60extern GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount;
@@ -49,6 +63,9 @@ extern GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount;
49extern GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame; 63extern GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame;
50extern GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile; 64extern GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile;
51extern GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream; 65extern GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
66extern GdipCreateBitmapFromHBITMAP_Proc fn_GdipCreateBitmapFromHBITMAP;
67extern GdipDrawImageRectRectI_Proc fn_GdipDrawImageRectRectI;
68extern GdipSetInterpolationMode_Proc fn_GdipSetInterpolationMode;
52extern GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0; 69extern GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
53extern SHCreateMemStream_Proc fn_SHCreateMemStream; 70extern SHCreateMemStream_Proc fn_SHCreateMemStream;
54extern GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap; 71extern GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
@@ -73,6 +90,11 @@ extern GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
73# undef GdipCreateBitmapFromFile 90# undef GdipCreateBitmapFromFile
74# undef GdipCreateBitmapFromStream 91# undef GdipCreateBitmapFromStream
75# undef GdipCreateBitmapFromScan0 92# undef GdipCreateBitmapFromScan0
93# undef GdipCreateBitmapFromHBITMAP
94# undef GdipCreateFromHDC
95# undef GdipDrawImageRectRectI
96# undef GdipSetInterpolationMode
97# undef GdipDeleteGraphics
76# undef SHCreateMemStream 98# undef SHCreateMemStream
77# undef GdipCreateHBITMAPFromBitmap 99# undef GdipCreateHBITMAPFromBitmap
78# undef GdipDisposeImage 100# undef GdipDisposeImage
@@ -96,6 +118,11 @@ extern GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
96# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile 118# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile
97# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream 119# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream
98# define GdipCreateBitmapFromScan0 fn_GdipCreateBitmapFromScan0 120# define GdipCreateBitmapFromScan0 fn_GdipCreateBitmapFromScan0
121# define GdipCreateBitmapFromHBITMAP fn_GdipCreateBitmapFromHBITMAP
122# define GdipCreateFromHDC fn_GdipCreateFromHDC
123# define GdipDrawImageRectRectI fn_GdipDrawImageRectRectI
124# define GdipSetInterpolationMode fn_GdipSetInterpolationMode
125# define GdipDeleteGraphics fn_GdipDeleteGraphics
99# define SHCreateMemStream fn_SHCreateMemStream 126# define SHCreateMemStream fn_SHCreateMemStream
100# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap 127# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap
101# define GdipDisposeImage fn_GdipDisposeImage 128# define GdipDisposeImage fn_GdipDisposeImage
diff --git a/src/w32image.c b/src/w32image.c
index 44eed087528..da4d6843ba9 100644
--- a/src/w32image.c
+++ b/src/w32image.c
@@ -42,6 +42,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
42#ifdef WINDOWSNT 42#ifdef WINDOWSNT
43GdiplusStartup_Proc fn_GdiplusStartup; 43GdiplusStartup_Proc fn_GdiplusStartup;
44GdiplusShutdown_Proc fn_GdiplusShutdown; 44GdiplusShutdown_Proc fn_GdiplusShutdown;
45GdipCreateFromHDC_Proc fn_GdipCreateFromHDC;
46GdipDeleteGraphics_Proc fn_GdipDeleteGraphics;
45GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize; 47GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
46GdipGetPropertyItem_Proc fn_GdipGetPropertyItem; 48GdipGetPropertyItem_Proc fn_GdipGetPropertyItem;
47GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount; 49GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount;
@@ -53,6 +55,9 @@ GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
53GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0; 55GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
54SHCreateMemStream_Proc fn_SHCreateMemStream; 56SHCreateMemStream_Proc fn_SHCreateMemStream;
55GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap; 57GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
58GdipCreateBitmapFromHBITMAP_Proc fn_GdipCreateBitmapFromHBITMAP;
59GdipDrawImageRectRectI_Proc fn_GdipDrawImageRectRectI;
60GdipSetInterpolationMode_Proc fn_GdipSetInterpolationMode;
56GdipDisposeImage_Proc fn_GdipDisposeImage; 61GdipDisposeImage_Proc fn_GdipDisposeImage;
57GdipGetImageHeight_Proc fn_GdipGetImageHeight; 62GdipGetImageHeight_Proc fn_GdipGetImageHeight;
58GdipGetImageWidth_Proc fn_GdipGetImageWidth; 63GdipGetImageWidth_Proc fn_GdipGetImageWidth;
@@ -80,6 +85,14 @@ gdiplus_init (void)
80 get_proc_addr (gdiplus_lib, "GdiplusShutdown"); 85 get_proc_addr (gdiplus_lib, "GdiplusShutdown");
81 if (!fn_GdiplusShutdown) 86 if (!fn_GdiplusShutdown)
82 return false; 87 return false;
88 fn_GdipCreateFromHDC = (GdipCreateFromHDC_Proc)
89 get_proc_addr (gdiplus_lib, "GdipCreateFromHDC");
90 if (!fn_GdipCreateFromHDC)
91 return false;
92 fn_GdipDeleteGraphics = (GdipDeleteGraphics_Proc)
93 get_proc_addr (gdiplus_lib, "GdipDeleteGraphics");
94 if (!fn_GdipDeleteGraphics)
95 return false;
83 fn_GdipGetPropertyItemSize = (GdipGetPropertyItemSize_Proc) 96 fn_GdipGetPropertyItemSize = (GdipGetPropertyItemSize_Proc)
84 get_proc_addr (gdiplus_lib, "GdipGetPropertyItemSize"); 97 get_proc_addr (gdiplus_lib, "GdipGetPropertyItemSize");
85 if (!fn_GdipGetPropertyItemSize) 98 if (!fn_GdipGetPropertyItemSize)
@@ -120,6 +133,18 @@ gdiplus_init (void)
120 get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap"); 133 get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap");
121 if (!fn_GdipCreateHBITMAPFromBitmap) 134 if (!fn_GdipCreateHBITMAPFromBitmap)
122 return false; 135 return false;
136 fn_GdipCreateBitmapFromHBITMAP = (GdipCreateBitmapFromHBITMAP_Proc)
137 get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromHBITMAP");
138 if (!fn_GdipCreateBitmapFromHBITMAP)
139 return false;
140 fn_GdipDrawImageRectRectI = (GdipDrawImageRectRectI_Proc)
141 get_proc_addr (gdiplus_lib, "GdipDrawImageRectRectI");
142 if (!fn_GdipDrawImageRectRectI)
143 return false;
144 fn_GdipSetInterpolationMode = (GdipSetInterpolationMode_Proc)
145 get_proc_addr (gdiplus_lib, "GdipSetInterpolationMode");
146 if (!fn_GdipSetInterpolationMode)
147 return false;
123 fn_GdipDisposeImage = (GdipDisposeImage_Proc) 148 fn_GdipDisposeImage = (GdipDisposeImage_Proc)
124 get_proc_addr (gdiplus_lib, "GdipDisposeImage"); 149 get_proc_addr (gdiplus_lib, "GdipDisposeImage");
125 if (!fn_GdipDisposeImage) 150 if (!fn_GdipDisposeImage)
diff --git a/src/w32term.c b/src/w32term.c
index 88622700386..e18f39dd2a8 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -24,6 +24,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24#include "blockinput.h" 24#include "blockinput.h"
25#include "w32term.h" 25#include "w32term.h"
26#include "w32common.h" /* for OS version info */ 26#include "w32common.h" /* for OS version info */
27#include <wtypes.h>
28#include <gdiplus.h>
29#include "w32gdiplus.h"
27 30
28#include <ctype.h> 31#include <ctype.h>
29#include <errno.h> 32#include <errno.h>
@@ -2106,16 +2109,53 @@ w32_draw_image_foreground (struct glyph_string *s)
2106 compat_hdc, s->slice.x, s->slice.y, SRCCOPY); 2109 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2107 else 2110 else
2108 { 2111 {
2109 int pmode = 0; 2112#ifdef HAVE_NATIVE_IMAGE_API
2110 /* Windows 9X doesn't support HALFTONE. */ 2113 if (s->img->smoothing && w32_gdiplus_startup ())
2111 if (os_subtype == OS_SUBTYPE_NT 2114 {
2112 && (pmode = SetStretchBltMode (s->hdc, HALFTONE)) != 0) 2115 GpGraphics *graphics;
2113 SetBrushOrgEx (s->hdc, 0, 0, NULL); 2116 if (GdipCreateFromHDC (s->hdc, &graphics) == Ok)
2114 StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height, 2117 {
2115 compat_hdc, orig_slice_x, orig_slice_y, 2118 GpBitmap *gp_bitmap;
2116 orig_slice_width, orig_slice_height, SRCCOPY); 2119 /* Can't create a GpBitmap from a HBITMAP that was
2117 if (pmode) 2120 ever selected into a DC, so we need to copy. */
2118 SetStretchBltMode (s->hdc, pmode); 2121 HBITMAP copy
2122 = CopyImage (GetCurrentObject (compat_hdc, OBJ_BITMAP),
2123 IMAGE_BITMAP, 0, 0, 0);
2124 if (GdipCreateBitmapFromHBITMAP (copy, NULL,
2125 &gp_bitmap) == Ok)
2126 {
2127 GdipSetInterpolationMode (graphics,
2128 InterpolationModeHighQualityBilinear);
2129 GdipDrawImageRectRectI (graphics,
2130 gp_bitmap, x, y,
2131 s->slice.width,
2132 s->slice.height,
2133 orig_slice_x,
2134 orig_slice_y,
2135 orig_slice_width,
2136 orig_slice_height,
2137 UnitPixel,
2138 NULL, NULL, NULL);
2139 GdipDisposeImage (gp_bitmap);
2140 }
2141 DeleteObject (copy);
2142 GdipDeleteGraphics (graphics);
2143 }
2144 }
2145 else
2146#endif
2147 {
2148 int pmode = 0;
2149 /* Windows 9X doesn't support HALFTONE. */
2150 if (os_subtype == OS_SUBTYPE_NT
2151 && (pmode = SetStretchBltMode (s->hdc, HALFTONE)) != 0)
2152 SetBrushOrgEx (s->hdc, 0, 0, NULL);
2153 StretchBlt (s->hdc, x, y, s->slice.width, s->slice.height,
2154 compat_hdc, orig_slice_x, orig_slice_y,
2155 orig_slice_width, orig_slice_height, SRCCOPY);
2156 if (pmode)
2157 SetStretchBltMode (s->hdc, pmode);
2158 }
2119 } 2159 }
2120 2160
2121 /* When the image has a mask, we can expect that at 2161 /* When the image has a mask, we can expect that at