From 41bf865329bbc2411203e9a90bc8dfd93ed5ef31 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 17 May 2019 18:41:22 -0700 Subject: [PATCH] Clean up and simplify image-type setup MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This also fixes an unlikely hang involving a circular image description. * src/dispextern.h (struct image.type): Now pointer-to-const. * src/image.c (struct image_type.init) [!WINDOWSNT]: Omit. (IMAGE_TYPE_INIT): New macro. (image_types): Now a small array-of-const, not a pointer. (CACHE_IMAGE_TYPE): Remove; the code’s simpler without it. (ADD_IMAGE_TYPE): Remove this macro, replacing with ... (add_image_type): ... this equivalent function. All uses changed. (define_image_type): Remove. All uses removed. (valid_image_p): Use FOR_EACH_TAIL_SAFE to avoid Emacs hanging if the user creates a circular description of an image. (xbm_type, xpm_type, pbm_type, png_type, jpeg_type, tiff_type) (gif_type, imagemagick_type, svg_type, gs_type): Remove; now done by image_types. (init_imagemagick_functions): Remove decl of nonexistent function. (gs_clear_image): Remove; all uses replaced by image_clear_image. (initialize_image_type): New function, which captures a lot of the previously-scattered WINDOWSNT ifdefs. (lookup_image_type): Use it. (reset_image_types): Remove. All uses removed. (syms_of_image): Don’t worry about ignoring image_types for pdumper, since it’s a constant now. --- src/dispextern.h | 2 +- src/emacs.c | 3 - src/image.c | 448 +++++++++-------------------------------------- src/lisp.h | 1 - 4 files changed, 88 insertions(+), 366 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index 619f4c07675..e86ea6a02ae 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3036,7 +3036,7 @@ struct image int hmargin, vmargin; /* Reference to the type of the image. */ - struct image_type *type; + struct image_type const *type; /* True means that loading the image failed. Don't try again. */ bool load_failed_p; diff --git a/src/emacs.c b/src/emacs.c index 86d2bc65ac7..fd46540ce22 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2494,9 +2494,6 @@ You must run Emacs in batch mode in order to dump it. */) # ifdef WINDOWSNT Vlibrary_cache = Qnil; # endif -# ifdef HAVE_WINDOW_SYSTEM - reset_image_types (); -# endif Vpurify_flag = tem; diff --git a/src/image.c b/src/image.c index 0779594989a..b82bf12aa5e 100644 --- a/src/image.c +++ b/src/image.c @@ -548,82 +548,29 @@ struct image_type /* Free resources of image IMG which is used on frame F. */ void (*free) (struct frame *f, struct image *img); +#ifdef WINDOWSNT /* Initialization function (used for dynamic loading of image libraries on Windows), or NULL if none. */ bool (*init) (void); - - /* Next in list of all supported image types. */ - struct image_type *next; + /* An initializer for the init field. */ +# define IMAGE_TYPE_INIT(f) f +#else +# define IMAGE_TYPE_INIT(f) +#endif }; -/* List of supported image types. Use define_image_type to add new - types. Use lookup_image_type to find a type for a given symbol. */ - -static struct image_type *image_types; - /* Forward function prototypes. */ -static struct image_type *lookup_image_type (Lisp_Object); +static struct image_type const *lookup_image_type (Lisp_Object); static void image_laplace (struct frame *, struct image *); static void image_emboss (struct frame *, struct image *); static void image_build_heuristic_mask (struct frame *, struct image *, Lisp_Object); -#ifdef WINDOWSNT -#define CACHE_IMAGE_TYPE(type, status) \ - do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0) -#else -#define CACHE_IMAGE_TYPE(type, status) -#endif - -#define ADD_IMAGE_TYPE(type) \ - do { Vimage_types = Fcons (type, Vimage_types); } while (0) - -/* Define a new image type from TYPE. This adds a copy of TYPE to - image_types and caches the loading status of TYPE. */ -static struct image_type * -define_image_type (struct image_type *type) +static void +add_image_type (Lisp_Object type) { - struct image_type *p = NULL; - int new_type = type->type; - bool type_valid = true; - - block_input (); - - for (p = image_types; p; p = p->next) - if (p->type == new_type) - goto done; - - if (type->init) - { -#if defined HAVE_NTGUI && defined WINDOWSNT - /* If we failed to load the library before, don't try again. */ - Lisp_Object tested = Fassq (builtin_lisp_symbol (new_type), - Vlibrary_cache); - if (CONSP (tested) && NILP (XCDR (tested))) - type_valid = false; - else -#endif - { - type_valid = type->init (); - CACHE_IMAGE_TYPE (builtin_lisp_symbol (new_type), - type_valid ? Qt : Qnil); - } - } - - if (type_valid) - { - /* Make a copy of TYPE to avoid a bus error in a dumped Emacs. - The initialized data segment is read-only. */ - p = xmalloc (sizeof *p); - *p = *type; - p->next = image_types; - image_types = p; - } - - done: - unblock_input (); - return p; + Vimage_types = Fcons (type, Vimage_types); } @@ -637,29 +584,24 @@ define_image_type (struct image_type *type) bool valid_image_p (Lisp_Object object) { - bool valid_p = 0; - if (IMAGEP (object)) { - Lisp_Object tem; - - for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) - if (EQ (XCAR (tem), QCtype)) + Lisp_Object tail = XCDR (object); + FOR_EACH_TAIL_SAFE (tail) + if (EQ (XCAR (tail), QCtype)) { - tem = XCDR (tem); - if (CONSP (tem) && SYMBOLP (XCAR (tem))) + tail = XCDR (tail); + if (CONSP (tail)) { - struct image_type *type; - type = lookup_image_type (XCAR (tem)); + struct image_type const *type = lookup_image_type (XCAR (tail)); if (type) - valid_p = type->valid_p (object); + return type->valid_p (object); } - break; } } - return valid_p; + return false; } @@ -2575,8 +2517,6 @@ slurp_file (int fd, ptrdiff_t *size) XBM images ***********************************************************************/ -static bool xbm_load (struct frame *f, struct image *img); -static bool xbm_image_p (Lisp_Object object); static bool xbm_file_p (Lisp_Object); @@ -2620,18 +2560,6 @@ static const struct image_keyword xbm_format[XBM_LAST] = {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} }; -/* Structure describing the image type XBM. */ - -static struct image_type xbm_type = -{ - SYMBOL_INDEX (Qxbm), - xbm_image_p, - xbm_load, - image_clear_image, - NULL, - NULL -}; - /* Tokens returned from xbm_scan. */ enum xbm_token @@ -3357,13 +3285,6 @@ xbm_load (struct frame *f, struct image *img) XPM images ***********************************************************************/ -#if defined (HAVE_XPM) || defined (HAVE_NS) - -static bool xpm_image_p (Lisp_Object object); -static bool xpm_load (struct frame *f, struct image *img); - -#endif /* HAVE_XPM || HAVE_NS */ - #ifdef HAVE_XPM #ifdef HAVE_NTGUI /* Indicate to xpm.h that we don't have Xlib. */ @@ -3425,24 +3346,6 @@ static const struct image_keyword xpm_format[XPM_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_xpm_functions (void); -#else -#define init_xpm_functions NULL -#endif - -/* Structure describing the image type XPM. */ - -static struct image_type xpm_type = -{ - SYMBOL_INDEX (Qxpm), - xpm_image_p, - xpm_load, - image_clear_image, - init_xpm_functions, - NULL -}; - #ifdef HAVE_X_WINDOWS /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation @@ -5364,9 +5267,6 @@ image_build_heuristic_mask (struct frame *f, struct image *img, PBM (mono, gray, color) ***********************************************************************/ -static bool pbm_image_p (Lisp_Object object); -static bool pbm_load (struct frame *f, struct image *img); - /* Indices of image specification fields in gs_format, below. */ enum pbm_keyword_index @@ -5403,19 +5303,6 @@ static const struct image_keyword pbm_format[PBM_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -/* Structure describing the image type `pbm'. */ - -static struct image_type pbm_type = -{ - SYMBOL_INDEX (Qpbm), - pbm_image_p, - pbm_load, - image_clear_image, - NULL, - NULL -}; - - /* Return true if OBJECT is a valid PBM image specification. */ static bool @@ -5834,11 +5721,6 @@ pbm_load (struct frame *f, struct image *img) #if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO) -/* Function prototypes. */ - -static bool png_image_p (Lisp_Object object); -static bool png_load (struct frame *f, struct image *img); - /* Indices of image specification fields in png_format, below. */ enum png_keyword_index @@ -5873,24 +5755,6 @@ static const struct image_keyword png_format[PNG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_png_functions (void); -#else -#define init_png_functions NULL -#endif - -/* Structure describing the image type `png'. */ - -static struct image_type png_type = -{ - SYMBOL_INDEX (Qpng), - png_image_p, - png_load, - image_clear_image, - init_png_functions, - NULL -}; - /* Return true if OBJECT is a valid PNG image specification. */ static bool @@ -6518,9 +6382,6 @@ png_load (struct frame *f, struct image *img) #if defined (HAVE_JPEG) || defined (HAVE_NS) -static bool jpeg_image_p (Lisp_Object object); -static bool jpeg_load (struct frame *f, struct image *img); - /* Indices of image specification fields in gs_format, below. */ enum jpeg_keyword_index @@ -6555,24 +6416,6 @@ static const struct image_keyword jpeg_format[JPEG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_jpeg_functions (void); -#else -#define init_jpeg_functions NULL -#endif - -/* Structure describing the image type `jpeg'. */ - -static struct image_type jpeg_type = -{ - SYMBOL_INDEX (Qjpeg), - jpeg_image_p, - jpeg_load, - image_clear_image, - init_jpeg_functions, - NULL -}; - /* Return true if OBJECT is a valid JPEG image specification. */ static bool @@ -7150,9 +6993,6 @@ jpeg_load (struct frame *f, struct image *img) #if defined (HAVE_TIFF) || defined (HAVE_NS) -static bool tiff_image_p (Lisp_Object object); -static bool tiff_load (struct frame *f, struct image *img); - /* Indices of image specification fields in tiff_format, below. */ enum tiff_keyword_index @@ -7189,24 +7029,6 @@ static const struct image_keyword tiff_format[TIFF_LAST] = {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_tiff_functions (void); -#else -#define init_tiff_functions NULL -#endif - -/* Structure describing the image type `tiff'. */ - -static struct image_type tiff_type = -{ - SYMBOL_INDEX (Qtiff), - tiff_image_p, - tiff_load, - image_clear_image, - init_tiff_functions, - NULL -}; - /* Return true if OBJECT is a valid TIFF image specification. */ static bool @@ -7634,10 +7456,6 @@ tiff_load (struct frame *f, struct image *img) #if defined (HAVE_GIF) || defined (HAVE_NS) -static bool gif_image_p (Lisp_Object object); -static bool gif_load (struct frame *f, struct image *img); -static void gif_clear_image (struct frame *f, struct image *img); - /* Indices of image specification fields in gif_format, below. */ enum gif_keyword_index @@ -7674,24 +7492,6 @@ static const struct image_keyword gif_format[GIF_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_gif_functions (void); -#else -#define init_gif_functions NULL -#endif - -/* Structure describing the image type `gif'. */ - -static struct image_type gif_type = -{ - SYMBOL_INDEX (Qgif), - gif_image_p, - gif_load, - gif_clear_image, - init_gif_functions, - NULL -}; - /* Free X resources of GIF image IMG which is used on frame F. */ static void @@ -8289,10 +8089,6 @@ gif_load (struct frame *f, struct image *img) ImageMagick ***********************************************************************/ -static bool imagemagick_image_p (Lisp_Object); -static bool imagemagick_load (struct frame *, struct image *); -static void imagemagick_clear_image (struct frame *, struct image *); - /* Indices of image specification fields in imagemagick_format. */ enum imagemagick_keyword_index @@ -8341,25 +8137,6 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} }; -#if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_imagemagick_functions (void); -#else -#define init_imagemagick_functions NULL -#endif - -/* Structure describing the image type for any image handled via - ImageMagick. */ - -static struct image_type imagemagick_type = - { - SYMBOL_INDEX (Qimagemagick), - imagemagick_image_p, - imagemagick_load, - imagemagick_clear_image, - init_imagemagick_functions, - NULL - }; - /* Free X resources of imagemagick image IMG which is used on frame F. */ static void @@ -9137,9 +8914,6 @@ and `imagemagick-types-inhibit'. */) /* Function prototypes. */ -static bool svg_image_p (Lisp_Object object); -static bool svg_load (struct frame *f, struct image *img); - static bool svg_load_image (struct frame *, struct image *, char *, ptrdiff_t, char *); @@ -9177,27 +8951,6 @@ static const struct image_keyword svg_format[SVG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -# if defined HAVE_NTGUI && defined WINDOWSNT -static bool init_svg_functions (void); -# else -#define init_svg_functions NULL -# endif - -/* Structure describing the image type `svg'. Its the same type of - structure defined for all image formats, handled by emacs image - functions. See struct image_type in dispextern.h. */ - -static struct image_type svg_type = -{ - SYMBOL_INDEX (Qsvg), - svg_image_p, - svg_load, - image_clear_image, - init_svg_functions, - NULL -}; - - /* Return true if OBJECT is a valid SVG image specification. Do this by calling parse_image_spec and supplying the keywords that identify the SVG format. */ @@ -9621,10 +9374,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents, #ifdef HAVE_GHOSTSCRIPT -static bool gs_image_p (Lisp_Object object); -static bool gs_load (struct frame *f, struct image *img); -static void gs_clear_image (struct frame *f, struct image *img); - /* Indices of image specification fields in gs_format, below. */ enum gs_keyword_index @@ -9665,28 +9414,6 @@ static const struct image_keyword gs_format[GS_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -/* Structure describing the image type `ghostscript'. */ - -static struct image_type gs_type = -{ - SYMBOL_INDEX (Qpostscript), - gs_image_p, - gs_load, - gs_clear_image, - NULL, - NULL -}; - - -/* Free X resources of Ghostscript image IMG which is used on frame F. */ - -static void -gs_clear_image (struct frame *f, struct image *img) -{ - image_clear_image (f, img); -} - - /* Return true if OBJECT is a valid Ghostscript image specification. */ @@ -9965,87 +9692,86 @@ the library file(s) specified by `dynamic-library-alist'. */) return lookup_image_type (type) ? Qt : Qnil; } -/* 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 * -lookup_image_type (Lisp_Object type) +static bool +initialize_image_type (struct image_type const *type) { - /* Types pbm and xbm are built-in and always available. */ - if (EQ (type, Qpbm)) - return define_image_type (&pbm_type); - - if (EQ (type, Qxbm)) - return define_image_type (&xbm_type); +#ifdef WINDOWSNT + bool (*init) (void) = type->init; -#if defined (HAVE_XPM) || defined (HAVE_NS) - if (EQ (type, Qxpm)) - return define_image_type (&xpm_type); + if (init) + { + /* If we failed to load the library before, don't try again. */ + Lisp_Object typesym = builtin_lisp_symbol (type->type); + Lisp_Object tested = Fassq (typesym, Vlibrary_cache); + if (CONSP (tested) && NILP (XCDR (tested))) + return false; + bool type_valid = init (); + Vlibrary_cache = Fcons (Fcons (typesym, type_valid ? Qt : Qnil), + Vlibrary_cache); + return type_valid; + } #endif + return true; +} -#if defined (HAVE_JPEG) || defined (HAVE_NS) - if (EQ (type, Qjpeg)) - return define_image_type (&jpeg_type); -#endif +/* Array of supported image types. */ -#if defined (HAVE_TIFF) || defined (HAVE_NS) - if (EQ (type, Qtiff)) - return define_image_type (&tiff_type); +static struct image_type const image_types[] = +{ +#ifdef HAVE_GHOSTSCRIPT + { SYMBOL_INDEX (Qpostscript), gs_image_p, gs_load, image_clear_image }, #endif - -#if defined (HAVE_GIF) || defined (HAVE_NS) - if (EQ (type, Qgif)) - return define_image_type (&gif_type); +#ifdef HAVE_IMAGEMAGICK + { SYMBOL_INDEX (Qimagemagick), imagemagick_image_p, imagemagick_load, + imagemagick_clear_image }, #endif - -#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO) - if (EQ (type, Qpng)) - return define_image_type (&png_type); +#ifdef HAVE_RSVG + { SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image, + IMAGE_TYPE_INIT (init_svg_functions) }, #endif - -#if defined (HAVE_RSVG) - if (EQ (type, Qsvg)) - return define_image_type (&svg_type); +#if defined HAVE_PNG || defined HAVE_NS || defined USE_CAIRO + { SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image, + IMAGE_TYPE_INIT (init_png_functions) }, #endif - -#if defined (HAVE_IMAGEMAGICK) - if (EQ (type, Qimagemagick)) - return define_image_type (&imagemagick_type); +#if defined HAVE_GIF || defined HAVE_NS + { SYMBOL_INDEX (Qgif), gif_image_p, gif_load, gif_clear_image, + IMAGE_TYPE_INIT (init_gif_functions) }, #endif - -#ifdef HAVE_GHOSTSCRIPT - if (EQ (type, Qpostscript)) - return define_image_type (&gs_type); +#if defined HAVE_TIFF || defined HAVE_NS + { 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 + { SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image, + IMAGE_TYPE_INIT (init_jpeg_functions) }, +#endif +#if defined HAVE_XPM || defined HAVE_NS + { SYMBOL_INDEX (Qxpm), xpm_image_p, xpm_load, image_clear_image, + IMAGE_TYPE_INIT (init_xpm_functions) }, +#endif + { SYMBOL_INDEX (Qxbm), xbm_image_p, xbm_load, image_clear_image }, + { SYMBOL_INDEX (Qpbm), pbm_image_p, pbm_load, image_clear_image }, +}; - return NULL; -} - -#if defined HAVE_UNEXEC && defined HAVE_WINDOW_SYSTEM - -/* Reset image_types before dumping. - Called from Fdump_emacs. */ +/* Look up image type TYPE, and return a pointer to its image_type + structure. Return 0 if TYPE is not a known image type. */ -void -reset_image_types (void) +static struct image_type const * +lookup_image_type (Lisp_Object type) { - while (image_types) + for (int i = 0; i < ARRAYELTS (image_types); i++) { - struct image_type *next = image_types->next; - xfree (image_types); - image_types = next; + struct image_type const *r = &image_types[i]; + if (EQ (type, builtin_lisp_symbol (r->type))) + return initialize_image_type (r) ? r : NULL; } + return NULL; } -#endif + void syms_of_image (void) { - /* Initialize this only once; it will be reset before dumping. */ - /* The portable dumper will just leave it NULL, so no need to reset. */ - image_types = NULL; - PDUMPER_IGNORE (image_types); - /* Must be defined now because we're going to update it below, while defining the supported image types. */ DEFVAR_LISP ("image-types", Vimage_types, @@ -10096,7 +9822,7 @@ non-numeric, there is no explicit limit on the size of images. */); DEFSYM (QCmax_width, ":max-width"); DEFSYM (QCmax_height, ":max-height"); #ifdef HAVE_GHOSTSCRIPT - ADD_IMAGE_TYPE (Qpostscript); + add_image_type (Qpostscript); DEFSYM (QCloader, ":loader"); DEFSYM (QCpt_width, ":pt-width"); DEFSYM (QCpt_height, ":pt-height"); @@ -10136,44 +9862,44 @@ non-numeric, there is no explicit limit on the size of images. */); #endif DEFSYM (Qpbm, "pbm"); - ADD_IMAGE_TYPE (Qpbm); + add_image_type (Qpbm); DEFSYM (Qxbm, "xbm"); - ADD_IMAGE_TYPE (Qxbm); + add_image_type (Qxbm); #if defined (HAVE_XPM) || defined (HAVE_NS) DEFSYM (Qxpm, "xpm"); - ADD_IMAGE_TYPE (Qxpm); + add_image_type (Qxpm); #endif #if defined (HAVE_JPEG) || defined (HAVE_NS) DEFSYM (Qjpeg, "jpeg"); - ADD_IMAGE_TYPE (Qjpeg); + add_image_type (Qjpeg); #endif #if defined (HAVE_TIFF) || defined (HAVE_NS) DEFSYM (Qtiff, "tiff"); - ADD_IMAGE_TYPE (Qtiff); + add_image_type (Qtiff); #endif #if defined (HAVE_GIF) || defined (HAVE_NS) DEFSYM (Qgif, "gif"); - ADD_IMAGE_TYPE (Qgif); + add_image_type (Qgif); #endif #if defined (HAVE_PNG) || defined (HAVE_NS) DEFSYM (Qpng, "png"); - ADD_IMAGE_TYPE (Qpng); + add_image_type (Qpng); #endif #if defined (HAVE_IMAGEMAGICK) DEFSYM (Qimagemagick, "imagemagick"); - ADD_IMAGE_TYPE (Qimagemagick); + add_image_type (Qimagemagick); #endif #if defined (HAVE_RSVG) DEFSYM (Qsvg, "svg"); - ADD_IMAGE_TYPE (Qsvg); + add_image_type (Qsvg); #ifdef HAVE_NTGUI /* Other libraries used directly by svg code. */ DEFSYM (Qgdk_pixbuf, "gdk-pixbuf"); diff --git a/src/lisp.h b/src/lisp.h index 77f23be66b5..876b757bf3f 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3643,7 +3643,6 @@ extern void init_fringe_once (void); /* Defined in image.c. */ extern int x_bitmap_mask (struct frame *, ptrdiff_t); -extern void reset_image_types (void); extern void syms_of_image (void); #ifdef HAVE_JSON -- 2.39.2