From bb4d86b40c61443608280df3d0668d44845177a5 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Sat, 22 Sep 2012 22:10:24 +0800 Subject: [PATCH] Refactor image-type loading. * src/dispextern.h (struct image_type): Add new slot, storing a type initialization function. * src/image.c (define_image_type): Call the image initializer function if it is defined. Arguments and return value changed. (valid_image_p, make_image): Callers changed. (xbm_type, xpm_type, pbm_type, png_type, jpeg_type, tiff_type) (gif_type, imagemagick_type, svg_type, gs_type): Add initialization functions. (Finit_image_library): Call lookup_image_type. (CHECK_LIB_AVAILABLE): Macro deleted. (lookup_image_type): Call define_image_type here, rather than via Finit_image_library, and without using CHECK_LIB_AVAILABLE. (syms_of_image): Move define_image_type calls for xbm_type and pbm_type to lookup_image_type. --- src/ChangeLog | 18 ++++ src/dispextern.h | 4 + src/image.c | 217 +++++++++++++++++++++++++++++------------------ 3 files changed, 155 insertions(+), 84 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index b69d4bb711..b2f33494b7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2012-09-22 Chong Yidong + + * dispextern.h (struct image_type): Add new slot, storing a type + initialization function. + + * image.c (define_image_type): Call the image initializer function + if it is defined. Arguments and return value changed. + (valid_image_p, make_image): Callers changed. + (xbm_type, xpm_type, pbm_type, png_type, jpeg_type, tiff_type) + (gif_type, imagemagick_type, svg_type, gs_type): Add + initialization functions. + (Finit_image_library): Call lookup_image_type. + (CHECK_LIB_AVAILABLE): Macro deleted. + (lookup_image_type): Call define_image_type here, rather than via + Finit_image_library, and without using CHECK_LIB_AVAILABLE. + (syms_of_image): Move define_image_type calls for xbm_type and + pbm_type to lookup_image_type. + 2012-09-22 Eli Zaretskii * keyboard.c (timer_check_2): Move calculation of 'timers' and diff --git a/src/dispextern.h b/src/dispextern.h index 978a23e4f7..1faeeb19d5 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2767,6 +2767,10 @@ struct image_type /* Free resources of image IMG which is used on frame F. */ void (* free) (struct frame *f, struct image *img); + /* Initialization function (used for dynamic loading of image + libraries on Windows), or NULL if none. */ + int (* init) (Lisp_Object); + /* Next in list of all supported image types. */ struct image_type *next; }; diff --git a/src/image.c b/src/image.c index 8d690df8ab..0060d0d414 100644 --- a/src/image.c +++ b/src/image.c @@ -561,8 +561,8 @@ static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic; /* Function prototypes. */ -static Lisp_Object define_image_type (struct image_type *type, int loaded); -static struct image_type *lookup_image_type (Lisp_Object symbol); +static struct image_type *define_image_type (struct image_type *, Lisp_Object); +static struct image_type *lookup_image_type (Lisp_Object, Lisp_Object); static void image_error (const char *format, Lisp_Object, Lisp_Object); static void x_laplace (struct frame *, struct image *); static void x_emboss (struct frame *, struct image *); @@ -579,54 +579,54 @@ static int x_build_heuristic_mask (struct frame *, struct image *, 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. */ + image_types and caches the loading status of TYPE. -static Lisp_Object -define_image_type (struct image_type *type, int loaded) + LIBRARIES is an alist associating dynamic libraries to external + files implementing them, which is passed to the image library + initialization function if necessary. A nil value defaults to + Vdynamic_library_alist. */ + +static struct image_type * +define_image_type (struct image_type *type, Lisp_Object libraries) { - Lisp_Object success; + struct image_type *p = NULL; + Lisp_Object target_type = *type->type; + int type_valid = 1; - if (!loaded) - success = Qnil; - else + BLOCK_INPUT; + + for (p = image_types; p; p = p->next) + if (EQ (*p->type, target_type)) + goto done; + + if (type->init) { - struct image_type *p; - Lisp_Object target_type = *(type->type); - for (p = image_types; p; p = p->next) - if (EQ (*(p->type), target_type)) - return Qt; +#ifdef HAVE_NTGUI + /* If we failed to load the library before, don't try again. */ + Lisp_Object tested = Fassq (target_type, Vlibrary_cache); + if (CONSP (tested) && NILP (XCDR (tested))) + type_valid = 0; + else +#endif + { + type_valid = type->init (libraries); + CACHE_IMAGE_TYPE (target_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; - success = Qt; } - CACHE_IMAGE_TYPE (*type->type, success); - return success; -} - - -/* Look up image type SYMBOL, and return a pointer to its image_type - structure. Value is null if SYMBOL is not a known image type. */ - -static inline struct image_type * -lookup_image_type (Lisp_Object symbol) -{ - struct image_type *type; - - /* We must initialize the image-type if it hasn't been already. */ - if (NILP (Finit_image_library (symbol, Vdynamic_library_alist))) - return 0; /* unimplemented */ - - for (type = image_types; type; type = type->next) - if (EQ (symbol, *type->type)) - break; - - return type; + done: + UNBLOCK_INPUT; + return p; } @@ -653,7 +653,7 @@ valid_image_p (Lisp_Object object) if (CONSP (tem) && SYMBOLP (XCAR (tem))) { struct image_type *type; - type = lookup_image_type (XCAR (tem)); + type = lookup_image_type (XCAR (tem), Qnil); if (type) valid_p = type->valid_p (object); } @@ -986,7 +986,7 @@ make_image (Lisp_Object spec, EMACS_UINT hash) eassert (valid_image_p (spec)); img->dependencies = NILP (file) ? Qnil : list1 (file); - img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL)); + img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL), Qnil); eassert (img->type != NULL); img->spec = spec; img->lisp_data = Qnil; @@ -2262,6 +2262,7 @@ static struct image_type xbm_type = xbm_image_p, xbm_load, x_clear_image, + NULL, NULL }; @@ -3051,6 +3052,12 @@ static const struct image_keyword xpm_format[XPM_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_xpm_functions (Lisp_Object); +#else +#define init_xpm_functions NULL +#endif + /* Structure describing the image type XPM. */ static struct image_type xpm_type = @@ -3059,6 +3066,7 @@ static struct image_type xpm_type = xpm_image_p, xpm_load, x_clear_image, + init_xpm_functions, NULL }; @@ -4981,6 +4989,7 @@ static struct image_type pbm_type = pbm_image_p, pbm_load, x_clear_image, + NULL, NULL }; @@ -5387,6 +5396,12 @@ static const struct image_keyword png_format[PNG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_png_functions (Lisp_Object); +#else +#define init_png_functions NULL +#endif + /* Structure describing the image type `png'. */ static struct image_type png_type = @@ -5395,6 +5410,7 @@ static struct image_type png_type = png_image_p, png_load, x_clear_image, + init_png_functions, NULL }; @@ -6039,6 +6055,12 @@ static const struct image_keyword jpeg_format[JPEG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_jpeg_functions (Lisp_Object); +#else +#define init_jpeg_functions NULL +#endif + /* Structure describing the image type `jpeg'. */ static struct image_type jpeg_type = @@ -6047,6 +6069,7 @@ static struct image_type jpeg_type = jpeg_image_p, jpeg_load, x_clear_image, + init_jpeg_functions, NULL }; @@ -6624,6 +6647,12 @@ static const struct image_keyword tiff_format[TIFF_LAST] = {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_tiff_functions (Lisp_Object); +#else +#define init_tiff_functions NULL +#endif + /* Structure describing the image type `tiff'. */ static struct image_type tiff_type = @@ -6632,6 +6661,7 @@ static struct image_type tiff_type = tiff_image_p, tiff_load, x_clear_image, + init_tiff_functions, NULL }; @@ -7072,6 +7102,12 @@ static const struct image_keyword gif_format[GIF_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_gif_functions (Lisp_Object); +#else +#define init_gif_functions NULL +#endif + /* Structure describing the image type `gif'. */ static struct image_type gif_type = @@ -7080,6 +7116,7 @@ static struct image_type gif_type = gif_image_p, gif_load, gif_clear_image, + init_gif_functions, NULL }; @@ -7562,6 +7599,12 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} }; +#ifdef HAVE_NTGUI +static int init_imagemagick_functions (Lisp_Object); +#else +#define init_imagemagick_functions NULL +#endif + /* Structure describing the image type for any image handled via ImageMagick. */ @@ -7571,6 +7614,7 @@ static struct image_type imagemagick_type = imagemagick_image_p, imagemagick_load, imagemagick_clear_image, + init_imagemagick_functions, NULL }; @@ -8109,22 +8153,23 @@ static const struct image_keyword svg_format[SVG_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_svg_functions (Lisp_Object); +#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 = { - /* An identifier showing that this is an image structure for the SVG format. */ &Qsvg, - /* Handle to a function that can be used to identify a SVG file. */ svg_image_p, - /* Handle to function used to load a SVG file. */ svg_load, - /* Handle to function to free sresources for SVG. */ x_clear_image, - /* An internal field to link to the next image type in a list of - image types, will be filled in when registering the format. */ + init_svg_functions, NULL }; @@ -8504,6 +8549,12 @@ static const struct image_keyword gs_format[GS_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; +#ifdef HAVE_NTGUI +static int init_gs_functions (Lisp_Object); +#else +#define init_gs_functions NULL +#endif + /* Structure describing the image type `ghostscript'. */ static struct image_type gs_type = @@ -8512,6 +8563,7 @@ static struct image_type gs_type = gs_image_p, gs_load, gs_clear_image, + init_gs_functions, NULL }; @@ -8774,16 +8826,6 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") Initialization ***********************************************************************/ -#ifdef HAVE_NTGUI -/* Image types that rely on external libraries are loaded dynamically - if the library is available. */ -#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \ - define_image_type (image_type, init_lib_fn (libraries)) -#else -#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \ - define_image_type (image_type, 1) -#endif /* HAVE_NTGUI */ - DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0, doc: /* Initialize image library implementing image type TYPE. Return non-nil if TYPE is a supported image type. @@ -8793,61 +8835,71 @@ Libraries to load are specified in alist LIBRARIES (usually, the value of `dynamic-library-alist', which see). */) (Lisp_Object type, Lisp_Object libraries) { -#ifdef HAVE_NTGUI - /* Don't try to reload the library. */ - Lisp_Object tested = Fassq (type, Vlibrary_cache); - if (CONSP (tested)) - return XCDR (tested); -#endif + return lookup_image_type (type, libraries) ? 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. + + LIBRARIES is an alist associating dynamic libraries to external + files implementing them, which is passed to the image library + initialization function if necessary. A nil value defaults to + Vdynamic_library_alist. */ + +static struct image_type * +lookup_image_type (Lisp_Object type, Lisp_Object libraries) +{ + if (NILP (libraries)) + libraries = Vdynamic_library_alist; /* Types pbm and xbm are built-in and always available. */ - if (EQ (type, Qpbm) || EQ (type, Qxbm)) - return Qt; + if (EQ (type, Qpbm)) + return define_image_type (&pbm_type, libraries); + + if (EQ (type, Qxbm)) + return define_image_type (&xbm_type, libraries); #if defined (HAVE_XPM) || defined (HAVE_NS) if (EQ (type, Qxpm)) - return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries); + return define_image_type (&xpm_type, libraries); #endif #if defined (HAVE_JPEG) || defined (HAVE_NS) if (EQ (type, Qjpeg)) - return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries); + return define_image_type (&jpeg_type, libraries); #endif #if defined (HAVE_TIFF) || defined (HAVE_NS) if (EQ (type, Qtiff)) - return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries); + return define_image_type (&tiff_type, libraries); #endif #if defined (HAVE_GIF) || defined (HAVE_NS) if (EQ (type, Qgif)) - return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries); + return define_image_type (&gif_type, libraries); #endif #if defined (HAVE_PNG) || defined (HAVE_NS) if (EQ (type, Qpng)) - return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries); + return define_image_type (&png_type, libraries); #endif #if defined (HAVE_RSVG) if (EQ (type, Qsvg)) - return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); + return define_image_type (&svg_type, libraries); #endif #if defined (HAVE_IMAGEMAGICK) if (EQ (type, Qimagemagick)) - return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, - libraries); + return define_image_type (&imagemagick_type, libraries); #endif #ifdef HAVE_GHOSTSCRIPT if (EQ (type, Qpostscript)) - return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); + return define_image_type (&gs_type, libraries); #endif - /* If the type is not recognized, avoid testing it ever again. */ - CACHE_IMAGE_TYPE (type, Qnil); - return Qnil; + return NULL; } void @@ -8878,15 +8930,6 @@ as a ratio to the frame height and width. If the value is non-numeric, there is no explicit limit on the size of images. */); Vmax_image_size = make_float (MAX_IMAGE_SIZE); - DEFSYM (Qpbm, "pbm"); - ADD_IMAGE_TYPE (Qpbm); - - DEFSYM (Qxbm, "xbm"); - ADD_IMAGE_TYPE (Qxbm); - - define_image_type (&xbm_type, 1); - define_image_type (&pbm_type, 1); - DEFSYM (Qcount, "count"); DEFSYM (Qextension_data, "extension-data"); DEFSYM (Qdelay, "delay"); @@ -8930,6 +8973,12 @@ non-numeric, there is no explicit limit on the size of images. */); ); #endif + DEFSYM (Qpbm, "pbm"); + ADD_IMAGE_TYPE (Qpbm); + + DEFSYM (Qxbm, "xbm"); + ADD_IMAGE_TYPE (Qxbm); + #if defined (HAVE_XPM) || defined (HAVE_NS) DEFSYM (Qxpm, "xpm"); ADD_IMAGE_TYPE (Qxpm); -- 2.20.1