diff options
Diffstat (limited to 'src/image.c')
-rw-r--r-- | src/image.c | 219 |
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); |