emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Interest in nt_load_image?


From: Juan José García-Ripoll
Subject: Re: Interest in nt_load_image?
Date: Mon, 30 Mar 2020 09:54:26 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (windows-nt)

Eli Zaretskii <address@hidden> writes:
>> From: Juan José García-Ripoll
>>  <address@hidden>
>> 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
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 */
 
 
 
@@ -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);
 
 /* For each display (currently only one on w32), we have a structure that
    records information about it.  */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]