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_OFF([native-image-api], [use native API's (GDI+ on Windows) for JPEG/TIFF/GIFF/PNG])
+OPTION_DEFAULT_ON([native-image-api], [use native image APIs (GDI+ on Windows)])
OPTION_DEFAULT_ON([json], [don't compile with native JSON support])
OPTION_DEFAULT_ON([xft],[don't use XFT for anti aliased fonts])
NTLIB=
CM_OBJ="cm.o"
XARGS_LIMIT=
-HAVE_NATIVE_IMAGE_API=no
+NATIVE_IMAGE_API=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
# 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"
+ dnl FIXME: This should probably be supported for Cygwin/w32 as
+ dnl well, but the Cygwin build needs to link against -lgdiplus
if test "${with_native_image_api}" = yes; then
- AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use MS Windows GDI+ for images.])
- HAVE_NATIVE_IMAGE_API=yes
- W32_NATIVE_IMAGE_API="w32image.o"
+ AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.])
+ NATIVE_IMAGE_API="yes (w32)"
+ W32_OBJ="$W32_OBJ w32image.o"
fi
- W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o $W32_NATIVE_IMAGE_API"
W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdi32 -lcomdlg32"
W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32"
W32_RES_LINK="\$(EMACSRES)"
Does Emacs use cairo? ${HAVE_CAIRO}
Does Emacs use -llcms2? ${HAVE_LCMS2}
Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}
- Does Emacs use native API for images? ${HAVE_NATIVE_IMAGE_API}
+ Does Emacs use native APIs for images? ${NATIVE_IMAGE_API}
Does Emacs support sound? ${HAVE_SOUND}
Does Emacs use -lgpm? ${HAVE_GPM}
Does Emacs use -ldbus? ${HAVE_DBUS}
with --with-native-image-api, which automatically disables the use of
optional third party libraries for those formats.
+This feature is experimental, and needs to be turned on to be used.
+To turn this on, set the variable 'w32-use-native-image-API' to a
+non-nil value. Please report any bugs you find while using the native
+image API via "M-x report-emacs-bug".
+
\f
----------------------------------------------------------------------
This file is part of GNU Emacs.
/* Check that SPEC is a valid image specification for the given
image type. Value is true if SPEC is valid. */
- bool (*valid_p) (Lisp_Object spec, Lisp_Object type);
+ bool (*valid_p) (Lisp_Object spec);
/* Load IMG which is used on frame F from information contained in
IMG->spec. Value is true if successful. */
{
struct image_type const *type = lookup_image_type (XCAR (tail));
if (type)
- return type->valid_p (object, builtin_lisp_symbol (type->type));
+ return type->valid_p (object);
}
break;
}
return false;
}
-
/* Log error message with format string FORMAT and trailing arguments.
Signaling an error, e.g. when an image cannot be loaded, is not a
good idea because this would interrupt redisplay, and the error
break;
}
- if (EQ (key, QCtype) && !EQ (type, value))
+ if (EQ (key, QCtype)
+ && !(EQ (type, value) || EQ (type, Qnative_image)))
return false;
}
displayed is used. */
static bool
-xbm_image_p (Lisp_Object object, Lisp_Object type)
+xbm_image_p (Lisp_Object object)
{
struct image_keyword kw[XBM_LAST];
memcpy (kw, xbm_format, sizeof kw);
- if (!parse_image_spec (object, kw, XBM_LAST, type))
+ if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
return 0;
eassert (EQ (kw[XBM_TYPE].value, Qxbm));
bool success_p = 0;
Lisp_Object file_name;
- eassert (xbm_image_p (img->spec, Qxbm));
+ eassert (xbm_image_p (img->spec));
/* If IMG->spec specifies a file name, create a non-file spec from it. */
file_name = image_spec_value (img->spec, QCfile, NULL);
/* Value is true if OBJECT is a valid XPM image specification. */
static bool
-xpm_image_p (Lisp_Object object, Lisp_Object type)
+xpm_image_p (Lisp_Object object)
{
struct image_keyword fmt[XPM_LAST];
memcpy (fmt, xpm_format, sizeof fmt);
- return (parse_image_spec (object, fmt, XPM_LAST, type)
+ return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
/* Either `:file' or `:data' must be present. */
&& fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
/* Either no `:color-symbols' or it's a list of conses
/* Return true if OBJECT is a valid PBM image specification. */
static bool
-pbm_image_p (Lisp_Object object, Lisp_Object type)
+pbm_image_p (Lisp_Object object)
{
struct image_keyword fmt[PBM_LAST];
memcpy (fmt, pbm_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, PBM_LAST, type))
+ if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
return 0;
/* Must specify either :data or :file. */
/***********************************************************************
NATIVE IMAGE HANDLING
***********************************************************************/
-#if defined(HAVE_NATIVE_IMAGE_API) && defined(HAVE_NTGUI)
+
+static bool
+image_can_use_native_api (Lisp_Object type)
+{
+#if HAVE_NATIVE_IMAGE_API
+# ifdef HAVE_NTGUI
+ return w32_can_use_native_image_api (type);
+# else
+ return false;
+# endif
+#else
+ return false;
+#endif
+}
+
+#if HAVE_NATIVE_IMAGE_API
+
/*
* These functions are actually defined in the OS-native implementation
* file. Currently, for Windows GDI+ interface, w32image.c, but other
* operating systems can follow suit.
*/
-static bool
-init_native_image_functions (void)
-{
- return w32_gdiplus_startup ();
-}
-
/* Indices of image specification fields in native format, below. */
-
enum native_image_keyword_index
{
NATIVE_IMAGE_TYPE,
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-
static const struct image_keyword native_image_format[] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
/* Return true if OBJECT is a valid native API image specification. */
static bool
-native_image_p (Lisp_Object object, Lisp_Object type)
+native_image_p (Lisp_Object object)
{
struct image_keyword fmt[NATIVE_IMAGE_LAST];
memcpy (fmt, native_image_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, 10, type))
+ if (!parse_image_spec (object, fmt, 10, Qnative_image))
return 0;
/* Must specify either the :data or :file keyword. */
static bool
native_image_load (struct frame *f, struct image *img)
{
+
+# ifdef HAVE_NTGUI
return w32_load_image (f, img,
image_spec_value (img->spec, QCfile, NULL),
image_spec_value (img->spec, QCdata, NULL));
+# else
+ return 0;
+# endif
}
-#endif
+
+#endif /* HAVE_NATIVE_IMAGE_API */
\f
/***********************************************************************
/* Return true if OBJECT is a valid PNG image specification. */
static bool
-png_image_p (Lisp_Object object, Lisp_Object type)
+png_image_p (Lisp_Object object)
{
struct image_keyword fmt[PNG_LAST];
memcpy (fmt, png_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, PNG_LAST, type))
+ if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
return 0;
/* Must specify either the :data or :file keyword. */
/* Return true if OBJECT is a valid JPEG image specification. */
static bool
-jpeg_image_p (Lisp_Object object, Lisp_Object type)
+jpeg_image_p (Lisp_Object object)
{
struct image_keyword fmt[JPEG_LAST];
memcpy (fmt, jpeg_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, JPEG_LAST, type))
+ if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
return 0;
/* Must specify either the :data or :file keyword. */
/* Return true if OBJECT is a valid TIFF image specification. */
static bool
-tiff_image_p (Lisp_Object object, Lisp_Object type)
+tiff_image_p (Lisp_Object object)
{
struct image_keyword fmt[TIFF_LAST];
memcpy (fmt, tiff_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, TIFF_LAST, type))
+ if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
return 0;
/* Must specify either the :data or :file keyword. */
/* Return true if OBJECT is a valid GIF image specification. */
static bool
-gif_image_p (Lisp_Object object, Lisp_Object type)
+gif_image_p (Lisp_Object object)
{
struct image_keyword fmt[GIF_LAST];
memcpy (fmt, gif_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, GIF_LAST, type))
+ if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
return 0;
/* Must specify either the :data or :file keyword. */
identify the IMAGEMAGICK format. */
static bool
-imagemagick_image_p (Lisp_Object object, Lisp_Object type)
+imagemagick_image_p (Lisp_Object object)
{
struct image_keyword fmt[IMAGEMAGICK_LAST];
memcpy (fmt, imagemagick_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, type))
+ if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
return 0;
/* Must specify either the :data or :file keyword. */
identify the SVG format. */
static bool
-svg_image_p (Lisp_Object object, Lisp_Object type)
+svg_image_p (Lisp_Object object)
{
struct image_keyword fmt[SVG_LAST];
memcpy (fmt, svg_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, SVG_LAST, type))
+ if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
return 0;
/* Must specify either the :data or :file keyword. */
specification. */
static bool
-gs_image_p (Lisp_Object object, Lisp_Object type)
+gs_image_p (Lisp_Object object)
{
struct image_keyword fmt[GS_LAST];
Lisp_Object tem;
memcpy (fmt, gs_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, GS_LAST, type))
+ if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
return 0;
/* Bounding box must be a list or vector containing 4 integers. */
initialize_image_type (struct image_type const *type)
{
#ifdef WINDOWSNT
- Lisp_Object typesym, tested;
- bool (*init) (void) = type->init;
+ Lisp_Object typesym = builtin_lisp_symbol (type->type);
#ifdef HAVE_NATIVE_IMAGE_API
- if (init == init_native_image_functions)
- return init();
+ if (image_can_use_native_api (typesym))
+ return true;
#endif
- typesym = builtin_lisp_symbol (type->type);
- tested = Fassq (typesym, Vlibrary_cache);
+ Lisp_Object tested = Fassq (typesym, Vlibrary_cache);
/* If we failed to load the library before, don't try again. */
if (CONSP (tested))
return !NILP (XCDR (tested)) ? true : false;
+ bool (*init) (void) = type->init;
if (init)
{
bool type_valid = init ();
{ SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image,
IMAGE_TYPE_INIT (init_svg_functions) },
#endif
-#if defined HAVE_NATIVE_IMAGE_API
- { SYMBOL_INDEX (Qjpeg), native_image_p, native_image_load, image_clear_image,
- IMAGE_TYPE_INIT (init_native_image_functions) },
- { SYMBOL_INDEX (Qpng), native_image_p, native_image_load, image_clear_image,
- IMAGE_TYPE_INIT (init_native_image_functions) },
- { SYMBOL_INDEX (Qgif), native_image_p, native_image_load, image_clear_image,
- IMAGE_TYPE_INIT (init_native_image_functions) },
- { SYMBOL_INDEX (Qtiff), native_image_p, native_image_load, image_clear_image,
- IMAGE_TYPE_INIT (init_native_image_functions) },
-#endif
#if defined HAVE_PNG || defined HAVE_NS
{ SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image,
IMAGE_TYPE_INIT (init_png_functions) },
{ SYMBOL_INDEX (Qpbm), pbm_image_p, pbm_load, image_clear_image },
};
+#ifdef HAVE_NATIVE_IMAGE_API
+struct image_type native_image_type =
+ { SYMBOL_INDEX (Qnative_image), native_image_p, native_image_load,
+ image_clear_image };
+#endif
+
/* Look up image type TYPE, and return a pointer to its image_type
structure. Return 0 if TYPE is not a known image type. */
static struct image_type const *
lookup_image_type (Lisp_Object type)
{
+#ifdef HAVE_NATIVE_IMAGE_API
+ if (image_can_use_native_api (type))
+ return &native_image_type;
+#endif
+
for (int i = 0; i < ARRAYELTS (image_types); i++)
{
struct image_type const *r = &image_types[i];
if (EQ (type, builtin_lisp_symbol (r->type)))
-#ifdef HAVE_NATIVE_IMAGE_API
- /* We can have more than one backend for one image type. */
- if (initialize_image_type (r))
- return r;
-#else
return initialize_image_type (r) ? r : NULL;
-#endif
}
return NULL;
}
#endif /* HAVE_NTGUI */
#endif /* HAVE_RSVG */
+#if HAVE_NATIVE_IMAGE_API
+ DEFSYM (Qnative_image, "native-image");
+# ifdef HAVE_NTGUI
+ DEFSYM (Qgdiplus, "gdiplus");
+ DEFSYM (Qshlwapi, "shlwapi");
+# endif
+#endif
+
defsubr (&Sinit_image_library);
#ifdef HAVE_IMAGEMAGICK
defsubr (&Simagemagick_types);
term_w32select ();
-#ifdef HAVE_GDIPLUS
+#if HAVE_NATIVE_IMAGE_API
w32_gdiplus_shutdown ();
#endif
}
/* Optional RGBQUAD array for palette follows (see BITMAPINFO docs). */
} XImage;
+struct image;
+extern int w32_load_image (struct frame *f, struct image *img,
+ Lisp_Object spec_file, Lisp_Object spec_data);
+extern bool w32_can_use_native_image_api (Lisp_Object);
+extern void w32_gdiplus_shutdown (void);
+
#define FACE_DEFAULT (~0)
extern HINSTANCE hinst;
#include "lisp.h"
#include "dispextern.h"
#define COBJMACROS
+#ifdef MINGW_W64
+/* FIXME: Do we need to include objidl.h? */
#include <objidl.h>
+#endif
#include <wtypes.h>
#include <gdiplus.h>
#include <shlwapi.h>
#include "frame.h"
#include "coding.h"
-/*#define LINK_GDIPLUS_STATICALLY 1*/
+#ifdef WINDOWSNT
-#ifndef LINK_GDIPLUS_STATICALLY
-DEF_DLL_FN (GpStatus, GdiplusStartup, (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *));
+DEF_DLL_FN (GpStatus, GdiplusStartup,
+ (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *));
DEF_DLL_FN (VOID, GdiplusShutdown, (ULONG_PTR));
-DEF_DLL_FN (GpStatus, GdipGetPropertyItemSize, (GpImage *, PROPID, UINT *));
-DEF_DLL_FN (GpStatus, GdipGetPropertyItem, (GpImage *, PROPID, UINT, PropertyItem *));
+DEF_DLL_FN (GpStatus, GdipGetPropertyItemSize,
+ (GpImage *, PROPID, UINT *));
+DEF_DLL_FN (GpStatus, GdipGetPropertyItem,
+ (GpImage *, PROPID, UINT, PropertyItem *));
DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsCount, (GpImage *, UINT *));
-DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsList, (GpImage *, GUID *, UINT));
-DEF_DLL_FN (GpStatus, GdipImageGetFrameCount, (GpImage *, GDIPCONST GUID *, UINT *));
-DEF_DLL_FN (GpStatus, GdipImageSelectActiveFrame, (GpImage*, GDIPCONST GUID *, UINT));
+DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsList,
+ (GpImage *, GUID *, UINT));
+DEF_DLL_FN (GpStatus, GdipImageGetFrameCount,
+ (GpImage *, GDIPCONST GUID *, UINT *));
+DEF_DLL_FN (GpStatus, GdipImageSelectActiveFrame,
+ (GpImage*, GDIPCONST GUID *, UINT));
DEF_DLL_FN (GpStatus, GdipCreateBitmapFromFile, (WCHAR *, GpBitmap **));
DEF_DLL_FN (GpStatus, GdipCreateBitmapFromStream, (IStream *, GpBitmap **));
DEF_DLL_FN (IStream *, SHCreateMemStream, (const BYTE *pInit, UINT cbInit));
-DEF_DLL_FN (GpStatus, GdipCreateHBITMAPFromBitmap, (GpBitmap *, HBITMAP *, ARGB));
+DEF_DLL_FN (GpStatus, GdipCreateHBITMAPFromBitmap,
+ (GpBitmap *, HBITMAP *, ARGB));
DEF_DLL_FN (GpStatus, GdipDisposeImage, (GpImage *));
DEF_DLL_FN (GpStatus, GdipGetImageHeight, (GpImage *, UINT *));
DEF_DLL_FN (GpStatus, GdipGetImageWidth, (GpImage *, UINT *));
-#endif
-
-static int gdip_initialized = 0;
-static ULONG_PTR token;
-static GdiplusStartupInput input;
-static GdiplusStartupOutput output;
-bool
-w32_gdiplus_startup (void)
+static bool
+gdiplus_init (void)
{
HANDLE gdiplus_lib, shlwapi_lib;
- GpStatus status;
- if (gdip_initialized < 0)
- return 0;
- else if (gdip_initialized)
- return 1;
-
-#ifndef LINK_GDIPLUS_STATICALLY
- DEFSYM (Qgdiplus, "gdiplus");
- DEFSYM (Qshlwapi, "shlwapi");
- if (!(gdiplus_lib = w32_delayed_load (Qgdiplus))) {
- gdip_initialized = -1;
- return 0;
- }
- if (!(shlwapi_lib = w32_delayed_load (Qshlwapi))) {
- gdip_initialized = -1;
- return 0;
- }
+ if (!((gdiplus_lib = w32_delayed_load (Qgdiplus))
+ && (shlwapi_lib = w32_delayed_load (Qshlwapi))))
+ return false;
LOAD_DLL_FN (gdiplus_lib, GdiplusStartup);
LOAD_DLL_FN (gdiplus_lib, GdiplusShutdown);
LOAD_DLL_FN (gdiplus_lib, GdipDisposeImage);
LOAD_DLL_FN (gdiplus_lib, GdipGetImageHeight);
LOAD_DLL_FN (gdiplus_lib, GdipGetImageWidth);
- LOAD_DLL_FN (shlwapi_lib, SHCreateMemStream);
+ /* LOAD_DLL_FN (shlwapi_lib, SHCreateMemStream); */
+
+ /* The following terrible kludge is required to use native image API
+ on Windows before Vista, because SHCreateMemStream was not
+ exported by name in those versions, only by ordinal number. */
+ fn_SHCreateMemStream =
+ (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib,
+ "SHCreateMemStream");
+ if (!fn_SHCreateMemStream)
+ {
+ fn_SHCreateMemStream =
+ (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib,
+ MAKEINTRESOURCEA (12));
+ if (!fn_SHCreateMemStream)
+ return false;
+ }
+
+ return true;
+}
+
+# undef GdiplusStartup
+# undef GdiplusShutdown
+# undef GdipGetPropertyItemSize
+# undef GdipGetPropertyItem
+# undef GdipImageGetFrameDimensionsCount
+# undef GdipImageGetFrameDimensionsList
+# undef GdipImageGetFrameCount
+# undef GdipImageSelectActiveFrame
+# undef GdipCreateBitmapFromFile
+# undef GdipCreateBitmapFromStream
+# undef SHCreateMemStream
+# undef GdipCreateHBITMAPFromBitmap
+# undef GdipDisposeImage
+# undef GdipGetImageHeight
+# undef GdipGetImageWidth
# define GdiplusStartup fn_GdiplusStartup
# define GdiplusShutdown fn_GdiplusShutdown
# define GdipDisposeImage fn_GdipDisposeImage
# define GdipGetImageHeight fn_GdipGetImageHeight
# define GdipGetImageWidth fn_GdipGetImageWidth
-#endif
- input.GdiplusVersion = 1;
- input.DebugEventCallback = NULL;
- input.SuppressBackgroundThread = FALSE;
- input.SuppressExternalCodecs = FALSE;
+#endif /* WINDOWSNT */
- status = GdiplusStartup (&token, &input, &output);
- if (status == Ok)
- {
- gdip_initialized = 1;
- return 1;
- }
- else
+static int gdip_initialized;
+static bool gdiplus_started;
+static ULONG_PTR token;
+static GdiplusStartupInput input;
+static GdiplusStartupOutput output;
+
+
+/* Initialize GDI+, return true if successful. */
+static bool
+gdiplus_startup (void)
+{
+ GpStatus status;
+
+ if (gdiplus_started)
+ return true;
+#ifdef WINDOWSNT
+ if (!gdip_initialized)
+ gdip_initialized = gdiplus_init () ? 1 : -1;
+#else
+ gdip_initialized = 1;
+#endif
+ if (gdip_initialized > 0)
{
- gdip_initialized = -1;
- return 0;
+ input.GdiplusVersion = 1;
+ input.DebugEventCallback = NULL;
+ input.SuppressBackgroundThread = FALSE;
+ input.SuppressExternalCodecs = FALSE;
+
+ status = GdiplusStartup (&token, &input, &output);
+ if (status == Ok)
+ gdiplus_started = true;
+ return (status == Ok);
}
+ return false;
}
+/* This is called from term_ntproc. */
void
w32_gdiplus_shutdown (void)
{
- GdiplusShutdown (token);
+ if (gdiplus_started)
+ GdiplusShutdown (token);
+ gdiplus_started = false;
}
+bool
+w32_can_use_native_image_api (Lisp_Object type)
+{
+ if (!w32_use_native_image_api)
+ return false;
+ if (!(EQ (type, Qjpeg)
+ || EQ (type, Qpng)
+ || EQ (type, Qgif)
+ || EQ (type, Qtiff)
+ || EQ (type, Qnative_image)))
+ {
+ /* GDI+ can also display BMP, Exif, ICON, WMF, and EMF images.
+ But we don't yet support these in image.c. */
+ return false;
+ }
+ return gdiplus_startup ();
+}
static double
w32_frame_delay (GpBitmap *pBitmap, int frame)
GdipGetPropertyItemSize (pBitmap, PropertyTagFrameDelay, &size);
/* Allocate a buffer to receive the property item. */
- propertyItem = (PropertyItem*)malloc (size);
+ propertyItem = malloc (size);
if (propertyItem != NULL)
{
/* Get the property item. */
GdipGetPropertyItem (pBitmap, PropertyTagFrameDelay, size, propertyItem);
- delay = ((double)propertyItem[frame].length) / 100;
+ delay = propertyItem[frame].length / 100.0;
if (delay == 0)
{
/* In GIF files, unfortunately, delay is only specified for the first
frame. */
- delay = ((double)propertyItem[0].length) / 100;
+ delay = propertyItem[0].length / 100.0;
}
free (propertyItem);
}
return delay;
}
-static UINT
-w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes, double *delay)
+static GpStatus
+w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes,
+ double *delay)
{
UINT count, frameCount;
GUID pDimensionIDs[1];
{
status = GdipImageGetFrameDimensionsList (pBitmap, pDimensionIDs, 1);
status = GdipImageGetFrameCount (pBitmap, &pDimensionIDs[0], &frameCount);
- if ((status == Ok) && (frameCount > 1))
+ if (status == Ok && frameCount > 1)
{
if (frame < 0 || frame >= frameCount)
- {
- status = GenericError;
- }
+ status = GenericError;
else
{
- status = GdipImageSelectActiveFrame (pBitmap, &pDimensionIDs[0], frame);
+ status = GdipImageSelectActiveFrame (pBitmap, &pDimensionIDs[0],
+ frame);
*delay = w32_frame_delay (pBitmap, frame);
*nframes = frameCount;
}
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);
+ 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
if (STRINGP (specified_bg)
? w32_defined_color (f, SSDATA (specified_bg), &color, false, false)
: (w32_query_frame_background_color (f, &color), true))
- /* The user specified `:background', use that. */
+ /* 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 (ARGB) (red | green | blue);
}
- return ((DWORD) 0xff000000);
+ return (ARGB) 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;
+ Lisp_Object metadata;
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. */
+ /* This function only gets called if w32_gdiplus_startup was invoked
+ and succeeded. We have a valid token and GDI+ is active. */
if (STRINGP (spec_file))
{
if (w32_unicode_filenames)
{
- filename_to_utf16 (SSDATA (spec_file) , filename);
+ wchar_t filename[MAX_PATH];
+ filename_to_utf16 (SSDATA (spec_file), filename);
status = GdipCreateBitmapFromFile (filename, &pBitmap);
}
else
}
else if (STRINGP (spec_data))
{
- IStream *pStream = SHCreateMemStream ((BYTE *) SSDATA (spec_data),
+ IStream *pStream = SHCreateMemStream ((BYTE *) SDATA (spec_data),
SBYTES (spec_data));
if (pStream != NULL)
{
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;
+ /* In multiframe pictures, select the first frame. */
+ Lisp_Object lisp_index = Fplist_get (XCDR (img->spec), QCindex);
+ int index = FIXNATP (lisp_index) ? XFIXNAT (lisp_index) : 0;
+ int nframes;
+ double delay;
status = w32_select_active_frame (pBitmap, index, &nframes, &delay);
- if ((status == Ok))
+ if (status == Ok)
{
if (nframes > 1)
metadata = Fcons (Qcount, Fcons (make_fixnum (nframes), metadata));
if (delay)
metadata = Fcons (Qdelay, Fcons (make_float (delay), metadata));
}
+ else if (status == Win32Error) /* FIXME! */
+ status = Ok;
}
if (status == Ok)
{
- bg_color = w32_image_bg_color (f, img);
+ ARGB bg_color = w32_image_bg_color (f, img);
+ Emacs_Pixmap pixmap;
+
status = GdipCreateHBITMAPFromBitmap (pBitmap, &pixmap, bg_color);
if (status == Ok)
{
else
w32_unicode_filenames = 1;
+ DEFVAR_BOOL ("w32-use-native-image-API",
+ w32_use_native_image_api,
+ doc: /* Non-nil means use the native MS-Windows image API to display images.
+
+A value of nil means displaying images other than PBM and XBM requires
+optional supporting libraries to be installed.
+The native image API library used is GDI+ via GDIPLUS.DLL. This
+library is available only since W2K, therefore this variable is
+unconditionally set to nil on older systems. */);
+
+ /* For now, disabled by default, since this is an experimental feature. */
+#if 0 && HAVE_NATIVE_IMAGE_API
+ if (os_subtype == OS_9X)
+ w32_use_native_image_api = 0;
+ else
+ w32_use_native_image_api = 1;
+#else
+ w32_use_native_image_api = 0;
+#endif
/* FIXME: The following variable will be (hopefully) removed
before Emacs 25.1 gets released. */
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. */