From: "Juan José García-Ripoll" <juanjose.garciaripoll@gmail.com>
To: emacs-devel@gnu.org
Subject: Re: Interest in nt_load_image?
Date: Mon, 30 Mar 2020 09:54:26 +0200 [thread overview]
Message-ID: <86imimwa4t.fsf@csic.es> (raw)
In-Reply-To: 83k1324m60.fsf@gnu.org
[-- Attachment #1: Type: text/plain, Size: 2431 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Juan José García-Ripoll
>> <juanjose.garciaripoll@gmail.com>
>> I believe something similar can be done for Windows using GDI+, removing
>> the dependency on libpng, libjpeg and libtiff. Would that be ok or
>> interesting? Has anyone tried it before?
>
> Please point to the relevant APIs, to make the discussion more
> practical.
GDI+ is an evolution of GDI that supports arbitrary plug-ins for image formats,
both bitmaps and vector type. It is a bit more modern than GDI, from what I
get, but, just as GDI, it is not the modern standard for Windows 2D
displays. Indeed, it is old enough that it is also supported by Windows XP.
https://docs.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-gdi-start
GDI+ has a flat C interface that allows loading images, querying properties,
displaying them and converting them to older GDI formats.
https://docs.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-flatapi-flat
This interface is included with the Mingw64/32 headers.
I propose to use this last feature. I attach a patch that works with Emacs 28
(and probably also Emacs 27). The way it works:
- At configuration time, it works just as the NextStep (NS) system, disabling
the use of libpng, libjpeg, libtiff and libgif when the build system is
Mingw.
- In images such as PNG, GIF or TIFF, it currently does not use a bitmask for
display. Instead, it relies on GDI+'s convertion to HBITMAP, which allows
alpha blending with any background color of choice.
- In the C code, it replaces the load_jpeg, load_gif, etc, with a generic
w32_load_image() function in src/w32image.c. This function is heavily
inspired by ns_load_image() in src/nsimage.c.
The patch is not intrusive at all, I believe. It does not aim to replace
Emacs's engine for displaying images and fonts on Windows. Instead, it just
uses GDI+ for the conversion.
The only thing that is missing is a place to call GdipShutdown(). I do not know
how to add an exit handler for Emacs' C core.
I have tested that the patch works with some stock JPEG, GIF, PNG and TIFF
images, including multipage and transparency.
I have also verified that it is possible to convert all *.xpm icons to *.png
format and thus eliminate the need to include libXpm-noX.dll. Plus, the size of
the icons is reduced by 50%
Cheers,
--
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: 18400 bytes --]
diff --git a/configure.ac b/configure.ac
index a4daf14..4384bc9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2132,6 +2132,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,9 +2161,11 @@ 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"
- W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32"
+ AC_DEFINE(HAVE_GDIPLUS, 1, [Define to use MS Windows GDI+ for images.])
+ HAVE_GDIPLUS=yes
+ W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o w32image.o"
+ W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdiplus -lgdi32 -lcomdlg32"
+ W32_LIBS="$W32_LIBS -lmpr -lwinspool -lshlwapi -lole32 -lcomctl32"
W32_RES_LINK="\$(EMACSRES)"
CLIENTRES="emacsclient.res"
CLIENTW="emacsclientw\$(EXEEXT)"
@@ -3572,8 +3575,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 +3726,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 +3799,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 +3829,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
diff --git a/src/Makefile.in b/src/Makefile.in
index 552dd2e..0dc6133 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 65d5925..7cdd85c 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_NTGUI)
/* 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_NTGUI
# 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 init_w32_image_load_functions
+
+#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,26 @@ 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));
+}
+
+static bool
+init_w32_image_load_functions (void)
+{
+ fprintf(stderr, "Functions initialized\n");
+ return 1;
+}
+
+#define init_jpeg_functions init_w32_image_load_functions
+#endif /* HAVE_GDIPLUS */
+
+
#endif /* !HAVE_JPEG */
@@ -7472,7 +7509,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 +7562,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 +7940,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 init_w32_image_load_functions
+
#endif
@@ -7911,7 +7960,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_NTGUI)
/* Indices of image specification fields in gif_format, below. */
@@ -7973,7 +8022,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_NTGUI */
#ifdef HAVE_GIF
@@ -8502,6 +8551,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 init_w32_image_load_functions
+#endif /* HAVE_NTGUI */
+
#endif /* HAVE_GIF */
@@ -10164,19 +10224,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 +10375,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/w32image.c b/src/w32image.c
new file mode 100644
index 0000000..9292879
--- /dev/null
+++ b/src/w32image.c
@@ -0,0 +1,240 @@
+/* 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"
+
+static int
+gdiplus_initialized_p()
+{
+ static int gdip_initialized = 0;
+ static ULONG_PTR token;
+ static GdiplusStartupInput input;
+ static GdiplusStartupOutput output;
+ 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;
+ }
+ }
+ return 1;
+}
+
+static float
+w32_frame_delay(GpBitmap *pBitmap, int frame)
+{
+
+ UINT size;
+ PropertyItem *propertyItem;
+ float 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 = ((float)propertyItem[frame].length) / 100;
+ if (delay == 0)
+ {
+ /* In GIF files, unfortunately, delay is only specified for
+ the first frame */
+ delay = ((float)propertyItem[0].length) / 100;
+ }
+ // Free space
+ free(propertyItem);
+ }
+ return delay;
+}
+
+static UINT
+w32_select_active_frame(GpBitmap *pBitmap, int frame, int *nframes, float *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);
+ fprintf(stderr, "FrameCount: %d\n", (int)frameCount);
+ fprintf(stderr, " index: %d\n", frame);
+ 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;
+ float delay;
+
+ eassert (valid_image_p (img->spec));
+
+ if (!gdiplus_initialized_p ())
+ {
+ return 0;
+ }
+
+ 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 f8a8a72..ed67957 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -75,7 +75,8 @@ #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);
\f
/* For each display (currently only one on w32), we have a structure that
records information about it. */
next prev parent reply other threads:[~2020-03-30 7:54 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-29 19:33 Interest in nt_load_image? Juan José García-Ripoll
2020-03-29 21:55 ` Juan José García-Ripoll
2020-03-30 2:21 ` Eli Zaretskii
2020-03-30 7:54 ` Juan José García-Ripoll [this message]
2020-03-30 13:46 ` Eli Zaretskii
2020-03-30 14:36 ` Juan José García-Ripoll
2020-03-30 14:44 ` Juan José García-Ripoll
2020-03-30 15:50 ` Eli Zaretskii
2020-03-30 16:15 ` Juan José García-Ripoll
2020-03-30 16:37 ` Eli Zaretskii
2020-03-30 17:16 ` Stefan Monnier
2020-03-30 18:32 ` Eli Zaretskii
2020-03-30 18:41 ` Stefan Monnier
2020-03-30 18:57 ` Eli Zaretskii
2020-03-30 19:39 ` Stefan Monnier
2020-03-31 14:19 ` Eli Zaretskii
2020-03-30 18:06 ` Juan José García-Ripoll
2020-03-30 18:47 ` Eli Zaretskii
2020-03-30 18:53 ` Eli Zaretskii
2020-03-30 23:21 ` Juanma Barranquero
2020-03-31 8:01 ` Juan José García-Ripoll
2020-03-31 13:14 ` Juanma Barranquero
2020-03-31 14:50 ` Stefan Monnier
2020-03-31 15:25 ` Juanma Barranquero
2020-03-31 16:54 ` Stefan Monnier
2020-03-31 15:13 ` Juan José García-Ripoll
2020-03-31 15:28 ` Juanma Barranquero
2020-03-31 13:31 ` Eli Zaretskii
2020-03-30 15:14 ` Stefan Monnier
2020-03-30 15:57 ` Eli Zaretskii
2020-03-30 17:10 ` Stefan Monnier
2020-03-30 18:23 ` Eli Zaretskii
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86imimwa4t.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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).