From: "Juan José García-Ripoll" <juanjose.garciaripoll@gmail.com>
To: emacs-devel@gnu.org
Subject: Optional support for GDI+ on Windows (emacs-28)
Date: Mon, 30 Mar 2020 21:26:52 +0200 [thread overview]
Message-ID: <86lfnh8wzn.fsf@csic.es> (raw)
[-- Attachment #1: Type: text/plain, Size: 347 bytes --]
Here is a more canonical patch for the Windows port:
When emacs is configured with --with-gdiplus and it is built on Mingw,
--with-jpeg, --with-png, --with-tiff and --with-gif are disabled and
those image formats are implemented using Windows' GDI+ library.
--
Juan José García Ripoll
http://juanjose.garciaripoll.com
http://quinfog.hbar.es
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdiplus.diff --]
[-- Type: text/x-patch, Size: 21235 bytes --]
diff --git a/configure.ac b/configure.ac
index a4daf1414d..0808bd86b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,6 +433,7 @@ AC_DEFUN
OPTION_DEFAULT_ON([cairo],[don't compile with Cairo drawing])
OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support])
OPTION_DEFAULT_OFF([imagemagick],[compile with ImageMagick image support])
+OPTION_DEFAULT_ON([gdiplus], [disable use of GDI+ on Windows for JPEG/TIFF/GIFF/PNG])
OPTION_DEFAULT_ON([json], [don't compile with native JSON support])
OPTION_DEFAULT_ON([xft],[don't use XFT for anti aliased fonts])
@@ -2132,6 +2133,7 @@ AC_DEFUN
NTLIB=
CM_OBJ="cm.o"
XARGS_LIMIT=
+HAVE_GDIPLUS=no
if test "${HAVE_W32}" = "yes"; then
AC_DEFINE(HAVE_NTGUI, 1, [Define to use native MS Windows GUI.])
if test "$with_toolkit_scroll_bars" = "no"; then
@@ -2160,8 +2162,14 @@ AC_DEFUN
# the rc file), not a linker script.
W32_RES_LINK="-Wl,emacs.res"
else
- W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o"
- W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdi32 -lcomdlg32"
+ if test "${with_gdiplus}" = yes; then
+ AC_DEFINE(HAVE_GDIPLUS, 1, [Define to use MS Windows GDI+ for images.])
+ HAVE_GDIPLUS=yes
+ W32_GDIPLUS="w32image.o"
+ W32_GDILIBS="-lgdiplus -lshlwapi"
+ fi
+ W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o $W32_GDIPLUS"
+ W32_LIBS="$W32_LIBS -lwinmm -lusp10 $W32_GDILIBS -lgdi32 -lcomdlg32"
W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32"
W32_RES_LINK="\$(EMACSRES)"
CLIENTRES="emacsclient.res"
@@ -3572,8 +3580,8 @@ AC_DEFUN
### Use -ljpeg if available, unless '--with-jpeg=no'.
HAVE_JPEG=no
LIBJPEG=
-if test "${NS_IMPL_COCOA}" = yes; then
- : # Cocoa provides its own jpeg support, so do nothing.
+if test "${NS_IMPL_COCOA}" = yes || test "${HAVE_GDIPLUS}" = "yes"; then
+ : # Cocoa and Windows' GDI+ provide their own jpeg support, so do nothing.
elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes"; then
if test "${with_jpeg}" != "no"; then
AC_CACHE_CHECK([for jpeglib 6b or later],
@@ -3723,8 +3731,8 @@ AC_DEFUN
HAVE_PNG=no
LIBPNG=
PNG_CFLAGS=
-if test "${NS_IMPL_COCOA}" = yes; then
- : # Cocoa provides its own png support, so do nothing.
+if test "${NS_IMPL_COCOA}" = yes || test "${HAVE_GDIPLUS}" = "yes"; then
+ : # Cocoa and Windows' GDI+ provide their own png support, so do nothing.
elif test "${with_png}" != no; then
# mingw32 loads the library dynamically.
if test "$opsys" = mingw32; then
@@ -3796,7 +3804,9 @@ AC_DEFUN
### mingw32 doesn't use -ltiff, since it loads the library dynamically.
HAVE_TIFF=no
LIBTIFF=
-if test "${opsys}" = "mingw32"; then
+if test "${HAVE_GDIPLUS}" = "yes"; then
+ : # Windows' GDI+ supports TIFF
+elif test "${opsys}" = "mingw32"; then
if test "${with_tiff}" != "no"; then
AC_CHECK_HEADER(tiffio.h, HAVE_TIFF=yes, HAVE_TIFF=no)
fi
@@ -3824,7 +3834,9 @@ AC_DEFUN
### mingw32 doesn't use -lgif/-lungif, since it loads the library dynamically.
HAVE_GIF=no
LIBGIF=
-if test "${opsys}" = "mingw32"; then
+if test "${HAVE_GDIPLUS}" = "yes"; then
+ : # Windows' GDI+ supports TIFF
+elif test "${opsys}" = "mingw32"; then
if test "${with_gif}" != "no"; then
AC_CHECK_HEADER(gif_lib.h, HAVE_GIF=yes, HAVE_GIF=no)
fi
@@ -5707,6 +5719,7 @@ AC_DEFUN
Does Emacs use a png library? ${HAVE_PNG} $LIBPNG
Does Emacs use -lrsvg-2? ${HAVE_RSVG}
Does Emacs use cairo? ${HAVE_CAIRO}
+ Does Emacs use GDI+? ${HAVE_GDIPLUS}
Does Emacs use -llcms2? ${HAVE_LCMS2}
Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}
Does Emacs support sound? ${HAVE_SOUND}
diff --git a/etc/NEWS b/etc/NEWS
index 870d39f7ee..6fc327665d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -297,6 +297,12 @@ such as "2020-01-15T16:12:21-08:00".
'module-file-suffix' now has the value ".dylib" on macOS, but the
".so" suffix is supported as well.
++++
+** Emacs can now use Microsoft Windows GDI+ library to load bitmap images in
+JPEG, PNG, GIF and TIFF formats. This support is enabled with --with-gdiplus,
+which automatically disables the use of third party libraries for those
+formats.
+
\f
----------------------------------------------------------------------
This file is part of GNU Emacs.
diff --git a/src/Makefile.in b/src/Makefile.in
index 552dd2e50a..0dc613352b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -280,10 +280,12 @@ GNU_OBJC_CFLAGS=
## w32fns.o w32menu.c w32reg.o fringe.o fontset.o w32font.o w32term.o
## w32xfns.o w32select.o image.o w32uniscribe.o w32cygwinx.o if HAVE_W32,
## w32cygwinx.o if CYGWIN but not HAVE_W32, else empty.
+## w32image.o if we use GDI+
W32_OBJ=@W32_OBJ@
## -lkernel32 -luser32 -lusp10 -lgdi32 -lole32 -lcomdlg32 -lcomctl32
## -lwinspool if HAVE_W32,
## -lkernel32 if CYGWIN but not HAVE_W32, else empty.
+## -lshlwapi if we use GDI+
W32_LIBS=@W32_LIBS@
## emacs.res if HAVE_W32
@@ -435,7 +437,7 @@ SOME_MACHINE_OBJECTS =
fontset.o dbusbind.o cygw32.o \
nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o macfont.o \
w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \
- w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
+ w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32image.o w32xfns.o \
w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
xsettings.o xgselect.o termcap.o hbfont.o
diff --git a/src/image.c b/src/image.c
index 65d59254f0..b0af991af7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -18,6 +18,12 @@ Copyright (C) 1989, 1992-2020 Free Software Foundation, Inc.
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
+#ifdef HAVE_GDIPLUS
+#undef HAVE_JPEG
+#undef HAVE_PNG
+#undef HAVE_GIF
+#undef HAVE_TIFF
+#endif
#include <fcntl.h>
#include <unistd.h>
@@ -6235,7 +6241,7 @@ pbm_load (struct frame *f, struct image *img)
PNG
***********************************************************************/
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
/* Indices of image specification fields in png_format, below. */
@@ -6289,7 +6295,7 @@ png_image_p (Lisp_Object object)
#endif /* HAVE_PNG || HAVE_NS */
-#if defined HAVE_PNG && !defined HAVE_NS
+#if defined HAVE_PNG && !defined HAVE_NS && !defined HAVE_GDIPLUS
# ifdef WINDOWSNT
/* PNG library details. */
@@ -6889,8 +6895,19 @@ png_load (struct frame *f, struct image *img)
image_spec_value (img->spec, QCdata, NULL));
}
+#elif defined HAVE_GDIPLUS
-#endif /* HAVE_NS */
+static bool
+png_load (struct frame *f, struct image *img)
+{
+ return w32_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
+}
+
+#define init_png_functions w32_gdiplus_startup
+
+#endif /* HAVE_GDIPLUS */
\f
@@ -6898,7 +6915,7 @@ png_load (struct frame *f, struct image *img)
JPEG
***********************************************************************/
-#if defined (HAVE_JPEG) || defined (HAVE_NS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
/* Indices of image specification fields in gs_format, below. */
@@ -6950,7 +6967,7 @@ jpeg_image_p (Lisp_Object object)
return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
}
-#endif /* HAVE_JPEG || HAVE_NS */
+#endif /* HAVE_JPEG || HAVE_NS || HAVE_GDIPLUS */
#ifdef HAVE_JPEG
@@ -7464,6 +7481,19 @@ jpeg_load (struct frame *f, struct image *img)
}
#endif /* HAVE_NS */
+#ifdef HAVE_GDIPLUS
+static bool
+jpeg_load (struct frame *f, struct image *img)
+{
+ return w32_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
+}
+
+#define init_jpeg_functions w32_gdiplus_startup
+#endif /* HAVE_GDIPLUS */
+
+
#endif /* !HAVE_JPEG */
@@ -7472,7 +7502,7 @@ jpeg_load (struct frame *f, struct image *img)
TIFF
***********************************************************************/
-#if defined (HAVE_TIFF) || defined (HAVE_NS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
/* Indices of image specification fields in tiff_format, below. */
@@ -7525,7 +7555,7 @@ tiff_image_p (Lisp_Object object)
return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
}
-#endif /* HAVE_TIFF || HAVE_NS */
+#endif /* HAVE_TIFF || HAVE_NS || HAVE_GDIPLUS */
#ifdef HAVE_TIFF
@@ -7903,6 +7933,18 @@ tiff_load (struct frame *f, struct image *img)
image_spec_value (img->spec, QCdata, NULL));
}
+#elif defined HAVE_GDIPLUS
+
+static bool
+tiff_load (struct frame *f, struct image *img)
+{
+ return w32_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
+}
+
+#define init_tiff_functions w32_gdiplus_startup
+
#endif
@@ -7911,7 +7953,7 @@ tiff_load (struct frame *f, struct image *img)
GIF
***********************************************************************/
-#if defined (HAVE_GIF) || defined (HAVE_NS)
+#if defined (HAVE_GIF) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
/* Indices of image specification fields in gif_format, below. */
@@ -7973,7 +8015,7 @@ gif_image_p (Lisp_Object object)
return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
}
-#endif /* HAVE_GIF */
+#endif /* HAVE_GIF || HAVE_NS || HAVE_GDIPLUS */
#ifdef HAVE_GIF
@@ -8502,6 +8544,17 @@ gif_load (struct frame *f, struct image *img)
}
#endif /* HAVE_NS */
+#ifdef HAVE_NTGUI
+static bool
+gif_load (struct frame *f, struct image *img)
+{
+ return w32_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
+}
+#define init_gif_functions w32_gdiplus_startup
+#endif /* HAVE_NTGUI */
+
#endif /* HAVE_GIF */
@@ -10164,19 +10217,19 @@ initialize_image_type (struct image_type const *type)
{ SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image,
IMAGE_TYPE_INIT (init_svg_functions) },
#endif
-#if defined HAVE_PNG || defined HAVE_NS
+#if defined HAVE_PNG || defined HAVE_NS || defined HAVE_GDIPLUS
{ SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image,
IMAGE_TYPE_INIT (init_png_functions) },
#endif
-#if defined HAVE_GIF || defined HAVE_NS
+#if defined HAVE_GIF || defined HAVE_NS || defined HAVE_GDIPLUS
{ SYMBOL_INDEX (Qgif), gif_image_p, gif_load, gif_clear_image,
IMAGE_TYPE_INIT (init_gif_functions) },
#endif
-#if defined HAVE_TIFF || defined HAVE_NS
+#if defined HAVE_TIFF || defined HAVE_NS || defined HAVE_GDIPLUS
{ SYMBOL_INDEX (Qtiff), tiff_image_p, tiff_load, image_clear_image,
IMAGE_TYPE_INIT (init_tiff_functions) },
#endif
-#if defined HAVE_JPEG || defined HAVE_NS
+#if defined HAVE_JPEG || defined HAVE_NS || defined HAVE_GDIPLUS
{ SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image,
IMAGE_TYPE_INIT (init_jpeg_functions) },
#endif
@@ -10315,22 +10368,22 @@ syms_of_image (void)
add_image_type (Qxpm);
#endif
-#if defined (HAVE_JPEG) || defined (HAVE_NS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
DEFSYM (Qjpeg, "jpeg");
add_image_type (Qjpeg);
#endif
-#if defined (HAVE_TIFF) || defined (HAVE_NS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
DEFSYM (Qtiff, "tiff");
add_image_type (Qtiff);
#endif
-#if defined (HAVE_GIF) || defined (HAVE_NS)
+#if defined (HAVE_GIF) || defined (HAVE_NS) || defined (HAVE_GDIPLUS)
DEFSYM (Qgif, "gif");
add_image_type (Qgif);
#endif
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined(HAVE_GDIPLUS)
DEFSYM (Qpng, "png");
add_image_type (Qpng);
#endif
diff --git a/src/w32.c b/src/w32.c
index 698e10e234..1d2a52b6df 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10225,6 +10225,10 @@ term_ntproc (int ignored)
term_winsock ();
term_w32select ();
+
+#ifdef HAVE_GDIPLUS
+ w32_gdiplus_shutdown ();
+#endif
}
void
diff --git a/src/w32image.c b/src/w32image.c
new file mode 100644
index 0000000000..e8469b9c94
--- /dev/null
+++ b/src/w32image.c
@@ -0,0 +1,275 @@
+/* Implementation of GUI terminal on the Microsoft Windows API.
+
+Copyright (C) 1989, 1993-2020 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include "lisp.h"
+#include "dispextern.h"
+#define COBJMACROS
+#include <objidl.h>
+#include <wtypes.h>
+#include <gdiplus.h>
+#include <shlwapi.h>
+#include "w32term.h"
+#include "frame.h"
+#include "coding.h"
+
+
+#if 0
+/*
+ * The following code is not really needed, but it provides an illustration on
+ * how to probe the list of available codecs.
+ */
+
+static void
+print_wchar(FILE *stream, WCHAR *string)
+{
+ for ( ; *string; ++string) {
+ fputc (*string, stream);
+ }
+}
+
+static void
+w32_list_decoders (void)
+{
+ UINT ndecoders, size;
+ ImageCodecInfo *pCodec;
+ int i;
+
+ GdipGetImageDecodersSize(&ndecoders, &size);
+ pCodec = (ImageCodecInfo *)malloc(size);
+
+ GdipGetImageDecoders(ndecoders, size, pCodec);
+ for (i = 0; i < ndecoders; ++i)
+ {
+ fprintf(stderr, "\nCodec name: "); print_wchar (stderr, pCodec[i].CodecName);
+ fprintf(stderr, "\n format: "); print_wchar (stderr, pCodec[i].FormatDescription);
+ fprintf(stderr, "\n ext: "); print_wchar (stderr, pCodec[i].FilenameExtension);
+ fprintf(stderr, "\n mime: "); print_wchar (stderr, pCodec[i].MimeType);
+ }
+ fprintf(stderr, "\n");
+
+ free(pCodec);
+}
+#endif /* Unused */
+
+static int gdip_initialized = 0;
+static ULONG_PTR token;
+static GdiplusStartupInput input;
+static GdiplusStartupOutput output;
+
+bool
+w32_gdiplus_startup (void)
+{
+ GpStatus status;
+
+ if (gdip_initialized < 0)
+ return 0;
+ else if (gdip_initialized)
+ return 1;
+ else
+ {
+ input.GdiplusVersion = 1;
+ input.DebugEventCallback = NULL;
+ input.SuppressBackgroundThread = FALSE;
+ input.SuppressExternalCodecs = FALSE;
+
+ status = GdiplusStartup(&token, &input, &output);
+ if (status == Ok)
+ {
+ gdip_initialized = 1;
+ return 1;
+ }
+ else
+ {
+ gdip_initialized = -1;
+ return 0;
+ }
+ }
+}
+
+void
+w32_gdiplus_shutdown (void)
+{
+ GdiplusShutdown(token);
+}
+
+
+static double
+w32_frame_delay (GpBitmap *pBitmap, int frame)
+{
+ UINT size;
+ PropertyItem *propertyItem;
+ double delay = 0.0;
+
+ /* Assume that the image has a property item of type PropertyItemEquipMake.
+ Get the size of that property item. */
+ GdipGetPropertyItemSize(pBitmap, PropertyTagFrameDelay, &size);
+
+ /* Allocate a buffer to receive the property item. */
+ propertyItem = (PropertyItem*)malloc(size);
+ if (propertyItem != NULL)
+ {
+ /* Get the property item. */
+ GdipGetPropertyItem(pBitmap, PropertyTagFrameDelay, size, propertyItem);
+ delay = ((double)propertyItem[frame].length) / 100;
+ if (delay == 0)
+ {
+ /* In GIF files, unfortunately, delay is only specified for the first
+ frame. */
+ delay = ((double)propertyItem[0].length) / 100;
+ }
+ free(propertyItem);
+ }
+ return delay;
+}
+
+static UINT
+w32_select_active_frame(GpBitmap *pBitmap, int frame, int *nframes, double *delay)
+{
+ UINT count, frameCount;
+ GUID pDimensionIDs[1];
+ GpStatus status = Ok;
+
+ status = GdipImageGetFrameDimensionsCount(pBitmap, &count);
+ frameCount = *nframes = 0;
+ *delay = 0.0;
+ if (count)
+ {
+ status = GdipImageGetFrameDimensionsList (pBitmap, pDimensionIDs, 1);
+ status = GdipImageGetFrameCount (pBitmap, &pDimensionIDs[0], &frameCount);
+ if ((status == Ok) && (frameCount > 1))
+ {
+ if (frame < 0 || frame >= frameCount)
+ {
+ status = GenericError;
+ }
+ else
+ {
+ status = GdipImageSelectActiveFrame (pBitmap, &pDimensionIDs[0], frame);
+ *delay = w32_frame_delay (pBitmap, frame);
+ *nframes = frameCount;
+ }
+ }
+ }
+ return status;
+}
+
+static ARGB
+w32_image_bg_color(struct frame *f, struct image *img)
+{
+ /* png_color_16 *image_bg; */
+ Lisp_Object specified_bg
+ = Fplist_get (XCDR (img->spec), QCbackground);
+ Emacs_Color color;
+
+ /* If the user specified a color, try to use it; if not, use the
+ current frame background, ignoring any default background
+ color set by the image. */
+ if (STRINGP (specified_bg)
+ ? FRAME_TERMINAL (f)->defined_color_hook (f,
+ SSDATA (specified_bg),
+ &color,
+ false,
+ false)
+ : (FRAME_TERMINAL (f)->query_frame_background_color (f, &color),
+ true))
+ /* The user specified `:background', use that. */
+ {
+ DWORD red = (((DWORD) color.red) & 0xff00) << 8;
+ DWORD green = ((DWORD) color.green) & 0xff00;
+ DWORD blue = ((DWORD) color.blue) >> 8;
+ return red | green | blue;
+ }
+ return ((DWORD) 0xff000000);
+}
+
+int
+w32_load_image (struct frame *f, struct image *img,
+ Lisp_Object spec_file, Lisp_Object spec_data)
+{
+ Emacs_Pixmap pixmap;
+ GpStatus status = GenericError;
+ GpBitmap *pBitmap;
+ wchar_t filename[MAX_PATH];
+ ARGB bg_color;
+ Lisp_Object lisp_index, metadata;
+ unsigned int index, nframes;
+ double delay;
+
+ eassert (valid_image_p (img->spec));
+
+ /* This function only gets called if init_w32_gdiplus () was invoked. We have
+ a valid token and GDI+ is active. */
+ if (STRINGP (spec_file))
+ {
+ filename_to_utf16 (SSDATA (spec_file) , filename);
+ status = GdipCreateBitmapFromFile (filename, &pBitmap);
+ }
+ else if (STRINGP (spec_data))
+ {
+ IStream *pStream = SHCreateMemStream ((BYTE *) SSDATA (spec_data),
+ SBYTES (spec_data));
+ if (pStream != NULL)
+ {
+ status = GdipCreateBitmapFromStream (pStream, &pBitmap);
+ IStream_Release (pStream);
+ }
+ }
+
+ metadata = Qnil;
+ if (status == Ok)
+ {
+ /* In multiframe pictures, select the first one */
+ lisp_index = Fplist_get (XCDR (img->spec), QCindex);
+ index = FIXNUMP (lisp_index) ? XFIXNAT (lisp_index) : 0;
+ status = w32_select_active_frame (pBitmap, index, &nframes, &delay);
+ if ((status == Ok))
+ {
+ if (nframes > 1)
+ metadata = Fcons (Qcount, Fcons (make_fixnum (nframes), metadata));
+ if (delay)
+ metadata = Fcons (Qdelay, Fcons (make_float (delay), metadata));
+ }
+ }
+
+ if (status == Ok)
+ {
+ bg_color = w32_image_bg_color(f, img);
+ status = GdipCreateHBITMAPFromBitmap (pBitmap, &pixmap, bg_color);
+ if (status == Ok)
+ {
+ UINT width, height;
+ GdipGetImageWidth (pBitmap, &width);
+ GdipGetImageHeight (pBitmap, &height);
+ img->width = width;
+ img->height = height;
+ img->pixmap = pixmap;
+ img->lisp_data = metadata;
+ }
+
+ GdipDisposeImage (pBitmap);
+ }
+
+ if (status != Ok)
+ {
+ add_to_log ("Unable to load image %s", img->spec);
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/w32term.h b/src/w32term.h
index f8a8a727e8..365d752767 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -75,7 +75,10 @@ #define CP_DEFAULT 1004
extern void w32_regenerate_palette (struct frame *f);
extern void w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal,
RECT *rect);
-
+extern int w32_load_image (struct frame *f, struct image *img,
+ Lisp_Object spec_file, Lisp_Object spec_data);
+extern bool w32_gdiplus_startup (void);
+extern void w32_gdiplus_shutdown (void);
\f
/* For each display (currently only one on w32), we have a structure that
records information about it. */
next reply other threads:[~2020-03-30 19:26 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-30 19:26 Juan José García-Ripoll [this message]
2020-03-31 14:12 ` Optional support for GDI+ on Windows (emacs-28) Eli Zaretskii
2020-03-31 15:35 ` Juan José García-Ripoll
2020-03-31 16:47 ` Eli Zaretskii
2020-03-31 16:57 ` Alan Third
2020-03-31 17:41 ` Eli Zaretskii
2020-03-31 19:36 ` Alan Third
2020-03-31 19:43 ` Stefan Monnier
2020-04-01 2:26 ` Eli Zaretskii
2020-04-01 18:33 ` Alan Third
2020-04-01 19:10 ` Eli Zaretskii
2020-03-31 17:27 ` Stefan Monnier
2020-03-31 17:52 ` Eli Zaretskii
2020-03-31 19:37 ` Stefan Monnier
2020-04-01 13:31 ` Eli Zaretskii
2020-04-01 14:58 ` Stefan Monnier
2020-04-01 15:45 ` Eli Zaretskii
2020-04-01 18:26 ` Stefan Monnier
2020-04-01 18:39 ` Juanma Barranquero
2020-04-01 19:22 ` Stefan Monnier
2020-04-01 19:24 ` Juanma Barranquero
2020-04-01 19:12 ` Eli Zaretskii
-- strict thread matches above, loose matches on Subject: below --
2020-03-30 23:09 Angelo Graziosi
2020-03-31 8:02 ` Juan José García-Ripoll
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86lfnh8wzn.fsf@csic.es \
--to=juanjose.garciaripoll@gmail.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.