summaryrefslogtreecommitdiff
path: root/src/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c219
1 files changed, 149 insertions, 70 deletions
diff --git a/src/image.c b/src/image.c
index 56878bcb8cb..e7e0a93313b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -24,7 +24,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* Include this before including <setjmp.h> to work around bugs with
older libpng; see Bug#17429. */
-#if defined HAVE_PNG && !defined HAVE_NS
+#if defined HAVE_PNG
# include <png.h>
#endif
@@ -125,6 +125,7 @@ typedef struct ns_bitmap_record Bitmap_Record;
#define NO_PIXMAP 0
#define PIX_MASK_RETAIN 0
+#define PIX_MASK_DRAW 1
#endif /* HAVE_NS */
@@ -816,7 +817,6 @@ valid_image_p (Lisp_Object object)
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
@@ -1004,7 +1004,8 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
break;
}
- if (EQ (key, QCtype) && !EQ (type, value))
+ if (EQ (key, QCtype)
+ && !(EQ (type, value) || EQ (type, Qnative_image)))
return false;
}
@@ -1620,7 +1621,7 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
static void
uncache_image (struct frame *f, Lisp_Object spec)
{
- struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
+ struct image *img = search_image_cache (f, spec, sxhash (spec));
if (img)
{
free_image (f, img);
@@ -2285,7 +2286,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
eassert (valid_image_p (spec));
/* Look up SPEC in the hash table of the image cache. */
- hash = sxhash (spec, 0);
+ hash = sxhash (spec);
img = search_image_cache (f, spec, hash);
if (img && img->load_failed_p)
{
@@ -4572,8 +4573,9 @@ xpm_scan (const char **s, const char *end, const char **beg, ptrdiff_t *len)
while (*s < end)
{
/* Skip white-space. */
- while (*s < end && (c = *(*s)++, c_isspace (c)))
- ;
+ do
+ c = *(*s)++;
+ while (c_isspace (c) && *s < end);
/* gnus-pointer.xpm uses '-' in its identifier.
sb-dir-plus.xpm uses '+' in its identifier. */
@@ -6232,10 +6234,104 @@ pbm_load (struct frame *f, struct image *img)
/***********************************************************************
+ NATIVE IMAGE HANDLING
+ ***********************************************************************/
+
+#if HAVE_NATIVE_IMAGE_API
+static bool
+image_can_use_native_api (Lisp_Object type)
+{
+# ifdef HAVE_NTGUI
+ return w32_can_use_native_image_api (type);
+# elif defined HAVE_NS
+ return ns_can_use_native_image_api (type);
+# else
+ return false;
+# endif
+}
+
+/*
+ * 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.
+ */
+
+/* Indices of image specification fields in native format, below. */
+enum native_image_keyword_index
+{
+ NATIVE_IMAGE_TYPE,
+ NATIVE_IMAGE_DATA,
+ NATIVE_IMAGE_FILE,
+ NATIVE_IMAGE_ASCENT,
+ NATIVE_IMAGE_MARGIN,
+ NATIVE_IMAGE_RELIEF,
+ NATIVE_IMAGE_ALGORITHM,
+ NATIVE_IMAGE_HEURISTIC_MASK,
+ NATIVE_IMAGE_MASK,
+ NATIVE_IMAGE_BACKGROUND,
+ NATIVE_IMAGE_INDEX,
+ NATIVE_IMAGE_LAST
+};
+
+/* 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},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
+};
+
+/* Return true if OBJECT is a valid native API image specification. */
+
+static bool
+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, Qnative_image))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[NATIVE_IMAGE_FILE].count + fmt[NATIVE_IMAGE_DATA].count == 1;
+}
+
+static bool
+native_image_load (struct frame *f, struct image *img)
+{
+ Lisp_Object image_file = image_spec_value (img->spec, QCfile, NULL);
+
+ if (STRINGP (image_file))
+ image_file = image_find_image_file (image_file);
+
+# ifdef HAVE_NTGUI
+ return w32_load_image (f, img, image_file,
+ image_spec_value (img->spec, QCdata, NULL));
+# elif defined HAVE_NS
+ return ns_load_image (f, img, image_file,
+ image_spec_value (img->spec, QCdata, NULL));
+# else
+ return 0;
+# endif
+}
+
+#endif /* HAVE_NATIVE_IMAGE_API */
+
+
+/***********************************************************************
PNG
***********************************************************************/
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG)
/* Indices of image specification fields in png_format, below. */
@@ -6286,10 +6382,10 @@ png_image_p (Lisp_Object object)
return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
}
-#endif /* HAVE_PNG || HAVE_NS */
+#endif /* HAVE_PNG */
-#if defined HAVE_PNG && !defined HAVE_NS
+#ifdef HAVE_PNG
# ifdef WINDOWSNT
/* PNG library details. */
@@ -6879,18 +6975,7 @@ png_load (struct frame *f, struct image *img)
return png_load_body (f, img, &c);
}
-#elif defined HAVE_NS
-
-static bool
-png_load (struct frame *f, struct image *img)
-{
- return ns_load_image (f, img,
- image_spec_value (img->spec, QCfile, NULL),
- image_spec_value (img->spec, QCdata, NULL));
-}
-
-
-#endif /* HAVE_NS */
+#endif /* HAVE_PNG */
@@ -6898,7 +6983,7 @@ png_load (struct frame *f, struct image *img)
JPEG
***********************************************************************/
-#if defined (HAVE_JPEG) || defined (HAVE_NS)
+#if defined (HAVE_JPEG)
/* Indices of image specification fields in gs_format, below. */
@@ -6950,7 +7035,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 */
#ifdef HAVE_JPEG
@@ -7452,18 +7537,6 @@ jpeg_load (struct frame *f, struct image *img)
return jpeg_load_body (f, img, &mgr);
}
-#else /* HAVE_JPEG */
-
-#ifdef HAVE_NS
-static bool
-jpeg_load (struct frame *f, struct image *img)
-{
- return ns_load_image (f, img,
- image_spec_value (img->spec, QCfile, NULL),
- image_spec_value (img->spec, QCdata, NULL));
-}
-#endif /* HAVE_NS */
-
#endif /* !HAVE_JPEG */
@@ -7472,7 +7545,7 @@ jpeg_load (struct frame *f, struct image *img)
TIFF
***********************************************************************/
-#if defined (HAVE_TIFF) || defined (HAVE_NS)
+#if defined (HAVE_TIFF)
/* Indices of image specification fields in tiff_format, below. */
@@ -7525,7 +7598,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 */
#ifdef HAVE_TIFF
@@ -7893,16 +7966,6 @@ tiff_load (struct frame *f, struct image *img)
return 1;
}
-#elif defined HAVE_NS
-
-static bool
-tiff_load (struct frame *f, struct image *img)
-{
- return ns_load_image (f, img,
- image_spec_value (img->spec, QCfile, NULL),
- image_spec_value (img->spec, QCdata, NULL));
-}
-
#endif
@@ -7911,7 +7974,7 @@ tiff_load (struct frame *f, struct image *img)
GIF
***********************************************************************/
-#if defined (HAVE_GIF) || defined (HAVE_NS)
+#if defined (HAVE_GIF)
/* Indices of image specification fields in gif_format, below. */
@@ -8211,7 +8274,10 @@ gif_load (struct frame *f, struct image *img)
rc = DGifSlurp (gif);
if (rc == GIF_ERROR || gif->ImageCount <= 0)
{
- image_error ("Error reading `%s'", img->spec);
+ if (NILP (specified_data))
+ image_error ("Error reading `%s'", img->spec);
+ else
+ image_error ("Error reading GIF data");
gif_close (gif, NULL);
return 0;
}
@@ -8490,18 +8556,6 @@ gif_load (struct frame *f, struct image *img)
return 1;
}
-#else /* !HAVE_GIF */
-
-#ifdef HAVE_NS
-static bool
-gif_load (struct frame *f, struct image *img)
-{
- return ns_load_image (f, img,
- image_spec_value (img->spec, QCfile, NULL),
- image_spec_value (img->spec, QCdata, NULL));
-}
-#endif /* HAVE_NS */
-
#endif /* HAVE_GIF */
@@ -10132,6 +10186,12 @@ initialize_image_type (struct image_type const *type)
{
#ifdef WINDOWSNT
Lisp_Object typesym = builtin_lisp_symbol (type->type);
+
+# if HAVE_NATIVE_IMAGE_API
+ if (image_can_use_native_api (typesym))
+ return true;
+# endif
+
Lisp_Object tested = Fassq (typesym, Vlibrary_cache);
/* If we failed to load the library before, don't try again. */
if (CONSP (tested))
@@ -10164,19 +10224,19 @@ static struct image_type const image_types[] =
{ 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
{ 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
{ 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
{ 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
{ SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image,
IMAGE_TYPE_INIT (init_jpeg_functions) },
#endif
@@ -10188,12 +10248,23 @@ static struct image_type const image_types[] =
{ SYMBOL_INDEX (Qpbm), pbm_image_p, pbm_load, image_clear_image },
};
+#if 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)
{
+#if 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];
@@ -10315,22 +10386,22 @@ non-numeric, there is no explicit limit on the size of images. */);
add_image_type (Qxpm);
#endif
-#if defined (HAVE_JPEG) || defined (HAVE_NS)
+#if defined (HAVE_JPEG) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qjpeg, "jpeg");
add_image_type (Qjpeg);
#endif
-#if defined (HAVE_TIFF) || defined (HAVE_NS)
+#if defined (HAVE_TIFF) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qtiff, "tiff");
add_image_type (Qtiff);
#endif
-#if defined (HAVE_GIF) || defined (HAVE_NS)
+#if defined (HAVE_GIF) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qgif, "gif");
add_image_type (Qgif);
#endif
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qpng, "png");
add_image_type (Qpng);
#endif
@@ -10354,6 +10425,14 @@ non-numeric, there is no explicit limit on the size of images. */);
#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);