X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8825930890470898883be9841d6a0aa3d6ff6623..218374939e60bfc5fb1e50178b7cffb9a0596479:/src/image.c diff --git a/src/image.c b/src/image.c index a3b64b7499..1c9b262c8c 100644 --- a/src/image.c +++ b/src/image.c @@ -1,5 +1,6 @@ /* Functions for image support on window system. - Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc. + +Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -18,8 +19,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include -#include #include #ifdef HAVE_PNG @@ -32,6 +31,8 @@ along with GNU Emacs. If not, see . */ #include +#include + /* This makes the fields of a Display accessible, in Xlib header files. */ #define XLIB_ILLEGAL_ACCESS @@ -48,11 +49,19 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "font.h" -#ifdef HAVE_X_WINDOWS -#include "xterm.h" -#include +#ifdef HAVE_SYS_STAT_H #include +#endif /* HAVE_SYS_STAT_H */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_WINDOW_SYSTEM +#include TERM_HEADER +#endif /* HAVE_WINDOW_SYSTEM */ + +#ifdef HAVE_X_WINDOWS #define COLOR_TABLE_SUPPORT 1 typedef struct x_bitmap_record Bitmap_Record; @@ -65,11 +74,8 @@ typedef struct x_bitmap_record Bitmap_Record; #define PIX_MASK_DRAW 1 #endif /* HAVE_X_WINDOWS */ - #ifdef HAVE_NTGUI #include "w32.h" -#include "w32term.h" - /* W32_TODO : Color tables on W32. */ #undef COLOR_TABLE_SUPPORT @@ -82,15 +88,9 @@ typedef struct w32_bitmap_record Bitmap_Record; #define PIX_MASK_RETAIN 0 #define PIX_MASK_DRAW 1 -#define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual #define x_defined_color w32_defined_color #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits) -/* Functions from w32term.c that depend on XColor (so can't go in w32term.h - without modifying lots of files). */ -extern void x_query_colors (struct frame *f, XColor *colors, int ncolors); -extern void x_query_color (struct frame *f, XColor *color); - /* Version of libpng that we were compiled with, or -1 if no PNG support was compiled in. This is tested by w32-win.el to correctly set up the alist used to search for PNG libraries. */ @@ -98,10 +98,6 @@ Lisp_Object Qlibpng_version; #endif /* HAVE_NTGUI */ #ifdef HAVE_NS -#include "nsterm.h" -#include -#include - #undef COLOR_TABLE_SUPPORT typedef struct ns_bitmap_record Bitmap_Record; @@ -115,10 +111,8 @@ typedef struct ns_bitmap_record Bitmap_Record; #define PIX_MASK_RETAIN 0 #define PIX_MASK_DRAW 1 -#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO (f)->visual #define x_defined_color(f, name, color_def, alloc) \ ns_defined_color (f, name, color_def, alloc, 0) -#define FRAME_X_SCREEN(f) 0 #define DefaultDepthOfScreen(screen) x_display_list->n_planes #endif /* HAVE_NS */ @@ -137,7 +131,6 @@ static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b); static void free_color_table (void); static unsigned long *colors_in_color_table (int *n); #endif -static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object); /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap id, which is just an int that this section returns. Bitmaps are @@ -319,11 +312,11 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) id = x_allocate_bitmap_record (f); dpyinfo->bitmaps[id - 1].img = bitmap; dpyinfo->bitmaps[id - 1].refcount = 1; - dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1); + dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1); dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap); dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap); - strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file)); + strcpy (dpyinfo->bitmaps[id - 1].file, SSDATA (file)); return id; #endif @@ -365,7 +358,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) dpyinfo->bitmaps[id - 1].pixmap = bitmap; dpyinfo->bitmaps[id - 1].have_mask = 0; dpyinfo->bitmaps[id - 1].refcount = 1; - dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1); + dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1); dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = height; dpyinfo->bitmaps[id - 1].width = width; @@ -414,9 +407,9 @@ x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id) if (--bm->refcount == 0) { - BLOCK_INPUT; + block_input (); free_bitmap_record (dpyinfo, bm); - UNBLOCK_INPUT; + unblock_input (); } } } @@ -477,19 +470,19 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) width = x_bitmap_width (f, id); height = x_bitmap_height (f, id); - BLOCK_INPUT; + block_input (); ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height, ~0, ZPixmap); if (!ximg) { - UNBLOCK_INPUT; + unblock_input (); return -1; } result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask); - UNBLOCK_INPUT; + unblock_input (); if (!result) { XDestroyImage (ximg); @@ -521,7 +514,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) } } - xassert (interrupt_input_blocked); + eassert (input_blocked_p ()); gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL); XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0, width, height); @@ -568,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 *); +static struct image_type *lookup_image_type (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 *); @@ -588,46 +581,47 @@ static int x_build_heuristic_mask (struct frame *, struct image *, /* Define a new image type from TYPE. This adds a copy of TYPE to image_types and caches the loading status of TYPE. */ -static Lisp_Object -define_image_type (struct image_type *type, int loaded) +static struct image_type * +define_image_type (struct image_type *type) { - 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) + { +#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 (); + 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. */ - struct image_type *p = (struct image_type *) xmalloc (sizeof *p); - memcpy (p, type, sizeof *p); + 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; } @@ -847,7 +841,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, break; default: - abort (); + emacs_abort (); break; } @@ -873,7 +867,7 @@ image_spec_value (Lisp_Object spec, Lisp_Object key, int *found) { Lisp_Object tail; - xassert (valid_image_p (spec)); + eassert (valid_image_p (spec)); for (tail = XCDR (spec); CONSP (tail) && CONSP (XCDR (tail)); @@ -982,14 +976,13 @@ static void free_image (struct frame *f, struct image *img); static struct image * make_image (Lisp_Object spec, EMACS_UINT hash) { - struct image *img = (struct image *) xmalloc (sizeof *img); + struct image *img = xzalloc (sizeof *img); Lisp_Object file = image_spec_value (spec, QCfile, NULL); - xassert (valid_image_p (spec)); - memset (img, 0, sizeof *img); + eassert (valid_image_p (spec)); img->dependencies = NILP (file) ? Qnil : list1 (file); img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL)); - xassert (img->type != NULL); + eassert (img->type != NULL); img->spec = spec; img->lisp_data = Qnil; img->ascent = DEFAULT_IMAGE_ASCENT; @@ -1061,11 +1054,8 @@ check_image_size (struct frame *f, int width, int height) void prepare_image_for_display (struct frame *f, struct image *img) { - EMACS_TIME t; - /* We're about to display IMG, so set its timestamp to `now'. */ - EMACS_GET_TIME (t); - img->timestamp = EMACS_SECS (t); + img->timestamp = current_emacs_time (); /* If IMG doesn't have a pixmap yet, load it now, using the image type dependent loader function. */ @@ -1333,9 +1323,9 @@ x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p, static void x_clear_image (struct frame *f, struct image *img) { - BLOCK_INPUT; + block_input (); x_clear_image_1 (f, img, 1, 1, 1); - UNBLOCK_INPUT; + unblock_input (); } @@ -1351,7 +1341,7 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name, XColor color; unsigned long result; - xassert (STRINGP (color_name)); + eassert (STRINGP (color_name)); if (x_defined_color (f, SSDATA (color_name), &color, 1) && img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors, @@ -1360,9 +1350,7 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name, /* This isn't called frequently so we get away with simply reallocating the color vector to the needed size, here. */ ptrdiff_t ncolors = img->ncolors + 1; - img->colors = - (unsigned long *) xrealloc (img->colors, - ncolors * sizeof *img->colors); + img->colors = xrealloc (img->colors, ncolors * sizeof *img->colors); img->colors[ncolors - 1] = color.pixel; img->ncolors = ncolors; result = color.pixel; @@ -1388,16 +1376,14 @@ static void postprocess_image (struct frame *, struct image *); struct image_cache * make_image_cache (void) { - struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c); + struct image_cache *c = xzalloc (sizeof *c); int size; - memset (c, 0, sizeof *c); size = 50; - c->images = (struct image **) xmalloc (size * sizeof *c->images); + c->images = xmalloc (size * sizeof *c->images); c->size = size; size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets; - c->buckets = (struct image **) xmalloc (size); - memset (c->buckets, 0, size); + c->buckets = xzalloc (size); return c; } @@ -1463,7 +1449,7 @@ free_image_cache (struct frame *f) ptrdiff_t i; /* Cache should not be referenced by any frame when freed. */ - xassert (c->refcount == 0); + eassert (c->refcount == 0); for (i = 0; i < c->used; ++i) free_image (f, c->images[i]); @@ -1494,7 +1480,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) /* Block input so that we won't be interrupted by a SIGIO while being in an inconsistent state. */ - BLOCK_INPUT; + block_input (); if (!NILP (filter)) { @@ -1513,8 +1499,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter) else if (INTEGERP (Vimage_cache_eviction_delay)) { /* Free cache based on timestamp. */ - EMACS_TIME t; - double old, delay; + EMACS_TIME old, t; + double delay; ptrdiff_t nimages = 0; for (i = 0; i < c->used; ++i) @@ -1528,13 +1514,13 @@ clear_image_cache (struct frame *f, Lisp_Object filter) delay = 1600 * delay / nimages / nimages; delay = max (delay, 1); - EMACS_GET_TIME (t); - old = EMACS_SECS (t) - delay; + t = current_emacs_time (); + old = sub_emacs_time (t, EMACS_TIME_FROM_DOUBLE (delay)); for (i = 0; i < c->used; ++i) { struct image *img = c->images[i]; - if (img && img->timestamp < old) + if (img && EMACS_TIME_LT (img->timestamp, old)) { free_image (f, img); ++nfreed; @@ -1560,7 +1546,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) ++windows_or_buffers_changed; } - UNBLOCK_INPUT; + unblock_input (); } } @@ -1707,12 +1693,11 @@ lookup_image (struct frame *f, Lisp_Object spec) { struct image *img; EMACS_UINT hash; - EMACS_TIME now; /* F must be a window-system frame, and SPEC must be a valid image specification. */ - xassert (FRAME_WINDOW_P (f)); - xassert (valid_image_p (spec)); + eassert (FRAME_WINDOW_P (f)); + eassert (valid_image_p (spec)); /* Look up SPEC in the hash table of the image cache. */ hash = sxhash (spec, 0); @@ -1726,7 +1711,7 @@ lookup_image (struct frame *f, Lisp_Object spec) /* If not found, create a new image and cache it. */ if (img == NULL) { - BLOCK_INPUT; + block_input (); img = make_image (spec, hash); cache_image (f, img); img->load_failed_p = img->type->load (f, img) == 0; @@ -1797,12 +1782,11 @@ lookup_image (struct frame *f, Lisp_Object spec) postprocess_image (f, img); } - UNBLOCK_INPUT; + unblock_input (); } /* We're using IMG, so set its timestamp to `now'. */ - EMACS_GET_TIME (now); - img->timestamp = EMACS_SECS (now); + img->timestamp = current_emacs_time (); /* Value is the image id. */ return img->id; @@ -1951,7 +1935,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, Window window = FRAME_X_WINDOW (f); Screen *screen = FRAME_X_SCREEN (f); - xassert (interrupt_input_blocked); + eassert (input_blocked_p ()); if (depth <= 0) depth = DefaultDepthOfScreen (screen); @@ -1974,7 +1958,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, } /* Allocate image raster. */ - (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height); + (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); /* Allocate a pixmap of the same size. */ *pixmap = XCreatePixmap (display, window, width, height, depth); @@ -2089,7 +2073,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, static void x_destroy_x_image (XImagePtr ximg) { - xassert (interrupt_input_blocked); + eassert (input_blocked_p ()); if (ximg) { #ifdef HAVE_X_WINDOWS @@ -2118,7 +2102,7 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he #ifdef HAVE_X_WINDOWS GC gc; - xassert (interrupt_input_blocked); + eassert (input_blocked_p ()); gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL); XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height); XFreeGC (FRAME_X_DISPLAY (f), gc); @@ -2133,7 +2117,7 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he #endif /* HAVE_NTGUI */ #ifdef HAVE_NS - xassert (ximg == pixmap); + eassert (ximg == pixmap); ns_retain_object (ximg); #endif } @@ -2188,7 +2172,7 @@ slurp_file (char *file, ptrdiff_t *size) if (stat (file, &st) == 0 && (fp = fopen (file, "rb")) != NULL && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX) - && (buf = (unsigned char *) xmalloc (st.st_size), + && (buf = xmalloc (st.st_size), fread (buf, 1, st.st_size, fp) == st.st_size)) { *size = st.st_size; @@ -2273,6 +2257,7 @@ static struct image_type xbm_type = xbm_image_p, xbm_load, x_clear_image, + NULL, NULL }; @@ -2323,7 +2308,7 @@ xbm_image_p (Lisp_Object object) if (!parse_image_spec (object, kw, XBM_LAST, Qxbm)) return 0; - xassert (EQ (kw[XBM_TYPE].value, Qxbm)); + eassert (EQ (kw[XBM_TYPE].value, Qxbm)); if (kw[XBM_FILE].count) { @@ -2365,7 +2350,7 @@ xbm_image_p (Lisp_Object object) for one line of the image. */ for (i = 0; i < height; ++i) { - Lisp_Object elt = XVECTOR (data)->contents[i]; + Lisp_Object elt = AREF (data, i); if (STRINGP (elt)) { @@ -2415,12 +2400,12 @@ xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival) loop: /* Skip white space. */ - while (*s < end && (c = *(*s)++, isspace (c))) + while (*s < end && (c = *(*s)++, c_isspace (c))) ; if (*s >= end) c = 0; - else if (isdigit (c)) + else if (c_isdigit (c)) { int value = 0, digit; @@ -2432,7 +2417,7 @@ xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival) while (*s < end) { c = *(*s)++; - if (isdigit (c)) + if (c_isdigit (c)) digit = c - '0'; else if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; @@ -2443,11 +2428,11 @@ xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival) value = 16 * value + digit; } } - else if (isdigit (c)) + else if (c_isdigit (c)) { value = c - '0'; while (*s < end - && (c = *(*s)++, isdigit (c))) + && (c = *(*s)++, c_isdigit (c))) value = 8 * value + c - '0'; } } @@ -2455,7 +2440,7 @@ xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival) { value = c - '0'; while (*s < end - && (c = *(*s)++, isdigit (c))) + && (c = *(*s)++, c_isdigit (c))) value = 10 * value + c - '0'; } @@ -2464,11 +2449,11 @@ xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival) *ival = value; c = XBM_TK_NUMBER; } - else if (isalpha (c) || c == '_') + else if (c_isalpha (c) || c == '_') { *sval++ = c; while (*s < end - && (c = *(*s)++, (isalnum (c) || c == '_'))) + && (c = *(*s)++, (c_isalnum (c) || c == '_'))) *sval++ = c; *sval = 0; if (*s < end) @@ -2508,7 +2493,7 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data) w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */ w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */ - bits = (unsigned char *) alloca (height * w2); + bits = alloca (height * w2); memset (bits, 0, height * w2); for (i = 0; i < height; i++) { @@ -2710,7 +2695,7 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e } bytes_per_line = (*width + 7) / 8 + padding_p; nbytes = bytes_per_line * *height; - p = *data = (char *) xmalloc (nbytes); + p = *data = xmalloc (nbytes); if (v10) { @@ -2784,7 +2769,7 @@ xbm_load_image (struct frame *f, struct image *img, unsigned char *contents, int non_default_colors = 0; Lisp_Object value; - xassert (img->width > 0 && img->height > 0); + eassert (img->width > 0 && img->height > 0); /* Get foreground and background colors, maybe allocate colors. */ value = image_spec_value (img->spec, QCforeground, NULL); @@ -2844,7 +2829,7 @@ xbm_load (struct frame *f, struct image *img) int success_p = 0; Lisp_Object file_name; - xassert (xbm_image_p (img->spec)); + 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); @@ -2890,14 +2875,14 @@ xbm_load (struct frame *f, struct image *img) memcpy (fmt, xbm_format, sizeof fmt); parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm); (void) parsed_p; - xassert (parsed_p); + eassert (parsed_p); /* Get specified width, and height. */ if (!in_memory_file_p) { img->width = XFASTINT (fmt[XBM_WIDTH].value); img->height = XFASTINT (fmt[XBM_HEIGHT].value); - xassert (img->width > 0 && img->height > 0); + eassert (img->width > 0 && img->height > 0); if (!check_image_size (f, img->width, img->height)) { image_error ("Invalid image size (see `max-image-size')", @@ -2935,10 +2920,10 @@ xbm_load (struct frame *f, struct image *img) char *p; int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR; - p = bits = (char *) alloca (nbytes * img->height); + p = bits = alloca (nbytes * img->height); for (i = 0; i < img->height; ++i, p += nbytes) { - Lisp_Object line = XVECTOR (data)->contents[i]; + Lisp_Object line = AREF (data, i); if (STRINGP (line)) memcpy (p, SDATA (line), nbytes); else @@ -2958,7 +2943,7 @@ xbm_load (struct frame *f, struct image *img) invertedBits = bits; nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * img->height; - bits = (char *) alloca (nbytes); + bits = alloca (nbytes); for (i = 0; i < nbytes; i++) bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]); } @@ -3062,6 +3047,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 (void); +#else +#define init_xpm_functions NULL +#endif + /* Structure describing the image type XPM. */ static struct image_type xpm_type = @@ -3070,6 +3061,7 @@ static struct image_type xpm_type = xpm_image_p, xpm_load, x_clear_image, + init_xpm_functions, NULL }; @@ -3123,8 +3115,7 @@ static void xpm_init_color_cache (struct frame *f, XpmAttributes *attrs) { size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache; - xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes); - memset (xpm_color_cache, 0, nbytes); + xpm_color_cache = xzalloc (nbytes); init_color_table (); if (attrs->valuemask & XpmColorSymbols) @@ -3188,7 +3179,7 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket) bucket = xpm_color_bucket (color_name); nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1; - p = (struct xpm_cached_color *) xmalloc (nbytes); + p = xmalloc (nbytes); strcpy (p->name, color_name); p->color = *color; p->next = xpm_color_cache[bucket]; @@ -3271,11 +3262,11 @@ DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **, DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *)); static int -init_xpm_functions (Lisp_Object libraries) +init_xpm_functions (void) { HMODULE library; - if (!(library = w32_delayed_load (libraries, Qxpm))) + if (!(library = w32_delayed_load (Qxpm))) return 0; LOAD_IMGLIB_FN (library, XpmFreeAttributes); @@ -3431,7 +3422,7 @@ xpm_load (struct frame *f, struct image *img) /* Allocate an XpmColorSymbol array. */ size = attrs.numsymbols * sizeof *xpm_syms; - xpm_syms = (XpmColorSymbol *) alloca (size); + xpm_syms = alloca (size); memset (xpm_syms, 0, size); attrs.colorsymbols = xpm_syms; @@ -3454,14 +3445,14 @@ xpm_load (struct frame *f, struct image *img) color = XCDR (XCAR (tail)); if (STRINGP (name)) { - xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1); + xpm_syms[i].name = alloca (SCHARS (name) + 1); strcpy (xpm_syms[i].name, SSDATA (name)); } else xpm_syms[i].name = empty_string; if (STRINGP (color)) { - xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1); + xpm_syms[i].value = alloca (SCHARS (color) + 1); strcpy (xpm_syms[i].value, SSDATA (color)); } else @@ -3584,7 +3575,7 @@ xpm_load (struct frame *f, struct image *img) img->width = attrs.width; img->height = attrs.height; - xassert (img->width > 0 && img->height > 0); + eassert (img->width > 0 && img->height > 0); /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */ #ifdef HAVE_NTGUI @@ -3672,16 +3663,17 @@ xpm_scan (const unsigned char **s, while (*s < end) { /* Skip white-space. */ - while (*s < end && (c = *(*s)++, isspace (c))) + while (*s < end && (c = *(*s)++, c_isspace (c))) ; /* gnus-pointer.xpm uses '-' in its identifier. sb-dir-plus.xpm uses '+' in its identifier. */ - if (isalpha (c) || c == '_' || c == '-' || c == '+') + if (c_isalpha (c) || c == '_' || c == '-' || c == '+') { *beg = *s - 1; while (*s < end - && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+')) + && (c = **s, c_isalnum (c) + || c == '_' || c == '-' || c == '+')) ++*s; *len = *s - *beg; return XPM_TK_IDENT; @@ -3748,7 +3740,7 @@ xpm_put_color_table_v (Lisp_Object color_table, int chars_len, Lisp_Object color) { - XVECTOR (color_table)->contents[*chars_start] = color; + ASET (color_table, *chars_start, color); } static Lisp_Object @@ -3756,7 +3748,7 @@ xpm_get_color_table_v (Lisp_Object color_table, const unsigned char *chars_start, int chars_len) { - return XVECTOR (color_table)->contents[*chars_start]; + return AREF (color_table, *chars_start); } static Lisp_Object @@ -3975,7 +3967,7 @@ xpm_load_image (struct frame *f, { if (xstrcasecmp (SSDATA (XCDR (specified_color)), "None") == 0) color_val = Qt; - else if (x_defined_color (f, SDATA (XCDR (specified_color)), + else if (x_defined_color (f, SSDATA (XCDR (specified_color)), &cdef, 0)) color_val = make_number (cdef.pixel); } @@ -4050,7 +4042,6 @@ xpm_load_image (struct frame *f, failure: image_error ("Invalid XPM file (%s)", img->spec, Qnil); - error: x_destroy_x_image (ximg); x_destroy_x_image (mask_img); x_clear_image (f, img); @@ -4083,7 +4074,7 @@ xpm_load (struct frame *f, return 0; } - contents = slurp_file (SDATA (file), &size); + contents = slurp_file (SSDATA (file), &size); if (contents == NULL) { image_error ("Error loading XPM image `%s'", img->spec, Qnil); @@ -4159,8 +4150,7 @@ static void init_color_table (void) { int size = CT_SIZE * sizeof (*ct_table); - ct_table = (struct ct_color **) xmalloc (size); - memset (ct_table, 0, size); + ct_table = xzalloc (size); ct_colors_allocated = 0; } @@ -4255,7 +4245,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) if (rc) { ++ct_colors_allocated; - p = (struct ct_color *) xmalloc (sizeof *p); + p = xmalloc (sizeof *p); p->r = r; p->g = g; p->b = b; @@ -4273,7 +4263,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) color = RGB_TO_ULONG (r, g, b); #endif /* HAVE_NTGUI */ ++ct_colors_allocated; - p = (struct ct_color *) xmalloc (sizeof *p); + p = xmalloc (sizeof *p); p->r = r; p->g = g; p->b = b; @@ -4316,19 +4306,19 @@ lookup_pixel_color (struct frame *f, unsigned long pixel) x_query_color (f, &color); rc = x_alloc_nearest_color (f, cmap, &color); #else - BLOCK_INPUT; + block_input (); cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f)); color.pixel = pixel; XQueryColor (NULL, cmap, &color); rc = x_alloc_nearest_color (f, cmap, &color); - UNBLOCK_INPUT; + unblock_input (); #endif /* HAVE_X_WINDOWS */ if (rc) { ++ct_colors_allocated; - p = (struct ct_color *) xmalloc (sizeof *p); + p = xmalloc (sizeof *p); p->r = color.red; p->g = color.green; p->b = color.blue; @@ -4360,8 +4350,7 @@ colors_in_color_table (int *n) } else { - colors = (unsigned long *) xmalloc (ct_colors_allocated - * sizeof *colors); + colors = xmalloc (ct_colors_allocated * sizeof *colors); *n = ct_colors_allocated; for (i = j = 0; i < CT_SIZE; ++i) @@ -4450,7 +4439,7 @@ x_to_xcolors (struct frame *f, struct image *img, int rgb_p) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height) memory_full (SIZE_MAX); - colors = (XColor *) xmalloc (sizeof *colors * img->width * img->height); + colors = xmalloc (sizeof *colors * img->width * img->height); #ifndef HAVE_NTGUI /* Get the X image IMG->pixmap. */ @@ -4469,9 +4458,8 @@ x_to_xcolors (struct frame *f, struct image *img, int rgb_p) p = colors; for (y = 0; y < img->height; ++y) { - XColor *row = p; - #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) + XColor *row = p; for (x = 0; x < img->width; ++x, ++p) p->pixel = GET_PIXEL (ximg, x, y); if (rgb_p) @@ -4604,7 +4592,7 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height) memory_full (SIZE_MAX); - new = (XColor *) xmalloc (sizeof *new * img->width * img->height); + new = xmalloc (sizeof *new * img->width * img->height); for (y = 0; y < img->height; ++y) { @@ -4754,14 +4742,12 @@ x_disable_image (struct frame *f, struct image *img) if (n_planes < 2 || cross_disabled_images) { #ifndef HAVE_NTGUI - Display *dpy = FRAME_X_DISPLAY (f); - GC gc; - #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ #define MaskForeground(f) WHITE_PIX_DEFAULT (f) - gc = XCreateGC (dpy, img->pixmap, 0, NULL); + Display *dpy = FRAME_X_DISPLAY (f); + GC gc = XCreateGC (dpy, img->pixmap, 0, NULL); XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f)); XDrawLine (dpy, img->pixmap, gc, 0, 0, img->width - 1, img->height - 1); @@ -4857,8 +4843,7 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how) #else /* Create the bit array serving as mask. */ row_width = (img->width + 7) / 8; - mask_img = xmalloc (row_width * img->height); - memset (mask_img, 0, row_width * img->height); + mask_img = xzalloc (row_width * img->height); /* Create a memory device context for IMG->pixmap. */ frame_dc = get_frame_dc (f); @@ -4999,6 +4984,7 @@ static struct image_type pbm_type = pbm_image_p, pbm_load, x_clear_image, + NULL, NULL }; @@ -5032,7 +5018,7 @@ pbm_scan_number (unsigned char **s, unsigned char *end) while (*s < end) { /* Skip white-space. */ - while (*s < end && (c = *(*s)++, isspace (c))) + while (*s < end && (c = *(*s)++, c_isspace (c))) ; if (c == '#') @@ -5041,11 +5027,11 @@ pbm_scan_number (unsigned char **s, unsigned char *end) while (*s < end && (c = *(*s)++, c != '\n')) ; } - else if (isdigit (c)) + else if (c_isdigit (c)) { /* Read decimal number. */ val = c - '0'; - while (*s < end && (c = *(*s)++, isdigit (c))) + while (*s < end && (c = *(*s)++, c_isdigit (c))) val = 10 * val + c - '0'; break; } @@ -5074,7 +5060,7 @@ pbm_read_file (Lisp_Object file, int *size) if (stat (SDATA (file), &st) == 0 && (fp = fopen (SDATA (file), "rb")) != NULL && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX) - && (buf = (char *) xmalloc (st.st_size), + && (buf = xmalloc (st.st_size), fread (buf, 1, st.st_size, fp) == st.st_size)) { *size = st.st_size; @@ -5405,6 +5391,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 (void); +#else +#define init_png_functions NULL +#endif + /* Structure describing the image type `png'. */ static struct image_type png_type = @@ -5413,6 +5405,7 @@ static struct image_type png_type = png_image_p, png_load, x_clear_image, + init_png_functions, NULL }; @@ -5471,11 +5464,11 @@ DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, siz #endif /* libpng version >= 1.5 */ static int -init_png_functions (Lisp_Object libraries) +init_png_functions (void) { HMODULE library; - if (!(library = w32_delayed_load (libraries, Qpng))) + if (!(library = w32_delayed_load (Qpng))) return 0; LOAD_IMGLIB_FN (library, png_get_io_ptr); @@ -5538,25 +5531,33 @@ init_png_functions (Lisp_Object libraries) #endif /* HAVE_NTGUI */ +/* Possibly inefficient/inexact substitutes for _setjmp and _longjmp. + Do not use sys_setjmp, as PNG supports only jmp_buf. The _longjmp + substitute may munge the signal mask, but that should be OK here. + MinGW (MS-Windows) uses _setjmp and defines setjmp to _setjmp in + the system header setjmp.h; don't mess up that. */ +#ifndef HAVE__SETJMP +# define _setjmp(j) setjmp (j) +# define _longjmp longjmp +#endif #if (PNG_LIBPNG_VER < 10500) -#define PNG_LONGJMP(ptr) (longjmp ((ptr)->jmpbuf, 1)) +#define PNG_LONGJMP(ptr) (_longjmp ((ptr)->jmpbuf, 1)) #define PNG_JMPBUF(ptr) ((ptr)->jmpbuf) #else /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */ #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1)) #define PNG_JMPBUF(ptr) \ - (*fn_png_set_longjmp_fn ((ptr), longjmp, sizeof (jmp_buf))) + (*fn_png_set_longjmp_fn ((ptr), _longjmp, sizeof (jmp_buf))) #endif /* Error and warning handlers installed when the PNG library is initialized. */ -static void my_png_error (png_struct *, const char *) NO_RETURN; -static void +static _Noreturn void my_png_error (png_struct *png_ptr, const char *msg) { - xassert (png_ptr != NULL); + eassert (png_ptr != NULL); /* Avoid compiler warning about deprecated direct access to png_ptr's fields in libpng versions 1.4.x. */ image_error ("PNG error: %s", build_string (msg), Qnil); @@ -5567,7 +5568,7 @@ my_png_error (png_struct *png_ptr, const char *msg) static void my_png_warning (png_struct *png_ptr, const char *msg) { - xassert (png_ptr != NULL); + eassert (png_ptr != NULL); image_error ("PNG warning: %s", build_string (msg), Qnil); } @@ -5616,20 +5617,31 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length) /* Load PNG image IMG for use on frame F. Value is non-zero if successful. */ +struct png_load_context +{ + /* These are members so that longjmp doesn't munge local variables. */ + png_struct *png_ptr; + png_info *info_ptr; + png_info *end_info; + FILE *fp; + png_byte *pixels; + png_byte **rows; +}; + static int -png_load (struct frame *f, struct image *img) +png_load_body (struct frame *f, struct image *img, struct png_load_context *c) { Lisp_Object file, specified_file; Lisp_Object specified_data; int x, y; ptrdiff_t i; XImagePtr ximg, mask_img = NULL; - png_struct *png_ptr = NULL; + png_struct *png_ptr; png_info *info_ptr = NULL, *end_info = NULL; - FILE *volatile fp = NULL; + FILE *fp = NULL; png_byte sig[8]; - png_byte * volatile pixels = NULL; - png_byte ** volatile rows = NULL; + png_byte *pixels = NULL; + png_byte **rows = NULL; png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_byte channels; @@ -5696,41 +5708,47 @@ png_load (struct frame *f, struct image *img) png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, my_png_error, my_png_warning); - if (!png_ptr) + if (png_ptr) { - if (fp) fclose (fp); - return 0; + info_ptr = fn_png_create_info_struct (png_ptr); + end_info = fn_png_create_info_struct (png_ptr); } - info_ptr = fn_png_create_info_struct (png_ptr); - if (!info_ptr) + c->png_ptr = png_ptr; + c->info_ptr = info_ptr; + c->end_info = end_info; + c->fp = fp; + c->pixels = pixels; + c->rows = rows; + + if (! (info_ptr && end_info)) { - fn_png_destroy_read_struct (&png_ptr, NULL, NULL); - if (fp) fclose (fp); - return 0; + fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info); + png_ptr = 0; } - - end_info = fn_png_create_info_struct (png_ptr); - if (!end_info) + if (! png_ptr) { - fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (fp) fclose (fp); return 0; } /* Set error jump-back. We come back here when the PNG library detects an error. */ - if (setjmp (PNG_JMPBUF (png_ptr))) + if (_setjmp (PNG_JMPBUF (png_ptr))) { error: - if (png_ptr) - fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); - xfree (pixels); - xfree (rows); - if (fp) fclose (fp); + if (c->png_ptr) + fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info); + xfree (c->pixels); + xfree (c->rows); + if (c->fp) + fclose (c->fp); return 0; } + /* Silence a bogus diagnostic; see GCC bug 54561. */ + IF_LINT (fp = c->fp); + /* Read image info. */ if (!NILP (specified_data)) fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory); @@ -5837,7 +5855,7 @@ png_load (struct frame *f, struct image *img) images with alpha channel, i.e. RGBA. If conversions above were sufficient we should only have 3 or 4 channels here. */ channels = fn_png_get_channels (png_ptr, info_ptr); - xassert (channels == 3 || channels == 4); + eassert (channels == 3 || channels == 4); /* Number of bytes needed for one row of the image. */ row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr); @@ -5846,8 +5864,8 @@ png_load (struct frame *f, struct image *img) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes) memory_full (SIZE_MAX); - pixels = (png_byte *) xmalloc (sizeof *pixels * row_bytes * height); - rows = (png_byte **) xmalloc (height * sizeof *rows); + c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height); + c->rows = rows = xmalloc (height * sizeof *rows); for (i = 0; i < height; ++i) rows[i] = pixels + i * row_bytes; @@ -5857,7 +5875,7 @@ png_load (struct frame *f, struct image *img) if (fp) { fclose (fp); - fp = NULL; + c->fp = NULL; } /* Create an image and pixmap serving as mask if the PNG image @@ -5932,7 +5950,7 @@ png_load (struct frame *f, struct image *img) #endif /* COLOR_TABLE_SUPPORT */ /* Clean up. */ - fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); + fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info); xfree (rows); xfree (pixels); @@ -5961,6 +5979,13 @@ png_load (struct frame *f, struct image *img) return 1; } +static int +png_load (struct frame *f, struct image *img) +{ + struct png_load_context c; + return png_load_body (f, img, &c); +} + #else /* HAVE_PNG */ #ifdef HAVE_NS @@ -6025,6 +6050,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 (void); +#else +#define init_jpeg_functions NULL +#endif + /* Structure describing the image type `jpeg'. */ static struct image_type jpeg_type = @@ -6033,6 +6064,7 @@ static struct image_type jpeg_type = jpeg_image_p, jpeg_load, x_clear_image, + init_jpeg_functions, NULL }; @@ -6088,11 +6120,11 @@ DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr * DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int)); static int -init_jpeg_functions (Lisp_Object libraries) +init_jpeg_functions (void) { HMODULE library; - if (!(library = w32_delayed_load (libraries, Qjpeg))) + if (!(library = w32_delayed_load (Qjpeg))) return 0; LOAD_IMGLIB_FN (library, jpeg_finish_decompress); @@ -6130,16 +6162,29 @@ jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired) struct my_jpeg_error_mgr { struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; + sys_jmp_buf setjmp_buffer; + + /* The remaining members are so that longjmp doesn't munge local + variables. */ + struct jpeg_decompress_struct cinfo; + enum + { + MY_JPEG_ERROR_EXIT, + MY_JPEG_INVALID_IMAGE_SIZE, + MY_JPEG_CANNOT_CREATE_X + } failure_code; +#ifdef lint + FILE *fp; +#endif }; -static void my_error_exit (j_common_ptr) NO_RETURN; -static void +static _Noreturn void my_error_exit (j_common_ptr cinfo) { struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err; - longjmp (mgr->setjmp_buffer, 1); + mgr->failure_code = MY_JPEG_ERROR_EXIT; + sys_longjmp (mgr->setjmp_buffer, 1); } @@ -6207,7 +6252,7 @@ our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes) reading the image. */ static void -jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len) +jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len) { struct jpeg_source_mgr *src; @@ -6345,17 +6390,15 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp) from the JPEG lib. */ static int -jpeg_load (struct frame *f, struct image *img) +jpeg_load_body (struct frame *f, struct image *img, + struct my_jpeg_error_mgr *mgr) { - struct jpeg_decompress_struct cinfo; - struct my_jpeg_error_mgr mgr; Lisp_Object file, specified_file; Lisp_Object specified_data; - FILE * volatile fp = NULL; + FILE *fp = NULL; JSAMPARRAY buffer; int row_stride, x, y; XImagePtr ximg = NULL; - int rc; unsigned long *colors; int width, height; @@ -6385,26 +6428,37 @@ jpeg_load (struct frame *f, struct image *img) return 0; } + IF_LINT (mgr->fp = fp); + /* Customize libjpeg's error handling to call my_error_exit when an error is detected. This function will perform a longjmp. */ - cinfo.err = fn_jpeg_std_error (&mgr.pub); - mgr.pub.error_exit = my_error_exit; - - if ((rc = setjmp (mgr.setjmp_buffer)) != 0) + mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub); + mgr->pub.error_exit = my_error_exit; + if (sys_setjmp (mgr->setjmp_buffer)) { - if (rc == 1) + switch (mgr->failure_code) { - /* Called from my_error_exit. Display a JPEG error. */ - char buf[JMSG_LENGTH_MAX]; - cinfo.err->format_message ((j_common_ptr) &cinfo, buf); - image_error ("Error reading JPEG image `%s': %s", img->spec, - build_string (buf)); + case MY_JPEG_ERROR_EXIT: + { + char buf[JMSG_LENGTH_MAX]; + mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf); + image_error ("Error reading JPEG image `%s': %s", img->spec, + build_string (buf)); + break; + } + + case MY_JPEG_INVALID_IMAGE_SIZE: + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + break; + + case MY_JPEG_CANNOT_CREATE_X: + break; } /* Close the input file and destroy the JPEG object. */ if (fp) - fclose ((FILE *) fp); - fn_jpeg_destroy_decompress (&cinfo); + fclose (fp); + fn_jpeg_destroy_decompress (&mgr->cinfo); /* If we already have an XImage, free that. */ x_destroy_x_image (ximg); @@ -6414,46 +6468,52 @@ jpeg_load (struct frame *f, struct image *img) return 0; } + /* Silence a bogus diagnostic; see GCC bug 54561. */ + IF_LINT (fp = mgr->fp); + /* Create the JPEG decompression object. Let it read from fp. Read the JPEG image header. */ - fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo)); + fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo); if (NILP (specified_data)) - jpeg_file_src (&cinfo, (FILE *) fp); + jpeg_file_src (&mgr->cinfo, fp); else - jpeg_memory_src (&cinfo, SDATA (specified_data), + jpeg_memory_src (&mgr->cinfo, SDATA (specified_data), SBYTES (specified_data)); - fn_jpeg_read_header (&cinfo, 1); + fn_jpeg_read_header (&mgr->cinfo, 1); /* Customize decompression so that color quantization will be used. Start decompression. */ - cinfo.quantize_colors = 1; - fn_jpeg_start_decompress (&cinfo); - width = img->width = cinfo.output_width; - height = img->height = cinfo.output_height; + mgr->cinfo.quantize_colors = 1; + fn_jpeg_start_decompress (&mgr->cinfo); + width = img->width = mgr->cinfo.output_width; + height = img->height = mgr->cinfo.output_height; if (!check_image_size (f, width, height)) { - image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); - longjmp (mgr.setjmp_buffer, 2); + mgr->failure_code = MY_JPEG_INVALID_IMAGE_SIZE; + sys_longjmp (mgr->setjmp_buffer, 1); } /* Create X image and pixmap. */ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) - longjmp (mgr.setjmp_buffer, 2); + { + mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; + sys_longjmp (mgr->setjmp_buffer, 1); + } /* Allocate colors. When color quantization is used, - cinfo.actual_number_of_colors has been set with the number of - colors generated, and cinfo.colormap is a two-dimensional array - of color indices in the range 0..cinfo.actual_number_of_colors. + mgr->cinfo.actual_number_of_colors has been set with the number of + colors generated, and mgr->cinfo.colormap is a two-dimensional array + of color indices in the range 0..mgr->cinfo.actual_number_of_colors. No more than 255 colors will be generated. */ { int i, ir, ig, ib; - if (cinfo.out_color_components > 2) + if (mgr->cinfo.out_color_components > 2) ir = 0, ig = 1, ib = 2; - else if (cinfo.out_color_components > 1) + else if (mgr->cinfo.out_color_components > 1) ir = 0, ig = 1, ib = 0; else ir = 0, ig = 0, ib = 0; @@ -6463,16 +6523,15 @@ jpeg_load (struct frame *f, struct image *img) a default color, and we don't have to care about which colors can be freed safely, and which can't. */ init_color_table (); - colors = (unsigned long *) alloca (cinfo.actual_number_of_colors - * sizeof *colors); + colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors); - for (i = 0; i < cinfo.actual_number_of_colors; ++i) + for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i) { /* Multiply RGB values with 255 because X expects RGB values in the range 0..0xffff. */ - int r = cinfo.colormap[ir][i] << 8; - int g = cinfo.colormap[ig][i] << 8; - int b = cinfo.colormap[ib][i] << 8; + int r = mgr->cinfo.colormap[ir][i] << 8; + int g = mgr->cinfo.colormap[ig][i] << 8; + int b = mgr->cinfo.colormap[ib][i] << 8; colors[i] = lookup_rgb_color (f, r, g, b); } @@ -6484,21 +6543,21 @@ jpeg_load (struct frame *f, struct image *img) } /* Read pixels. */ - row_stride = width * cinfo.output_components; - buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, - row_stride, 1); + row_stride = width * mgr->cinfo.output_components; + buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo, + JPOOL_IMAGE, row_stride, 1); for (y = 0; y < height; ++y) { - fn_jpeg_read_scanlines (&cinfo, buffer, 1); - for (x = 0; x < cinfo.output_width; ++x) + fn_jpeg_read_scanlines (&mgr->cinfo, buffer, 1); + for (x = 0; x < mgr->cinfo.output_width; ++x) XPutPixel (ximg, x, y, colors[buffer[0][x]]); } /* Clean up. */ - fn_jpeg_finish_decompress (&cinfo); - fn_jpeg_destroy_decompress (&cinfo); + fn_jpeg_finish_decompress (&mgr->cinfo); + fn_jpeg_destroy_decompress (&mgr->cinfo); if (fp) - fclose ((FILE *) fp); + fclose (fp); /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) @@ -6511,6 +6570,13 @@ jpeg_load (struct frame *f, struct image *img) return 1; } +static int +jpeg_load (struct frame *f, struct image *img) +{ + struct my_jpeg_error_mgr mgr; + return jpeg_load_body (f, img, &mgr); +} + #else /* HAVE_JPEG */ #ifdef HAVE_NS @@ -6576,6 +6642,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 (void); +#else +#define init_tiff_functions NULL +#endif + /* Structure describing the image type `tiff'. */ static struct image_type tiff_type = @@ -6584,6 +6656,7 @@ static struct image_type tiff_type = tiff_image_p, tiff_load, x_clear_image, + init_tiff_functions, NULL }; @@ -6624,11 +6697,11 @@ DEF_IMGLIB_FN (void, TIFFClose, (TIFF *)); DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t)); static int -init_tiff_functions (Lisp_Object libraries) +init_tiff_functions (void) { HMODULE library; - if (!(library = w32_delayed_load (libraries, Qtiff))) + if (!(library = w32_delayed_load (Qtiff))) return 0; LOAD_IMGLIB_FN (library, TIFFSetErrorHandler); @@ -6897,7 +6970,7 @@ tiff_load (struct frame *f, struct image *img) return 0; } - buf = (uint32 *) xmalloc (sizeof *buf * width * height); + buf = xmalloc (sizeof *buf * width * height); rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); @@ -7024,6 +7097,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 (void); +#else +#define init_gif_functions NULL +#endif + /* Structure describing the image type `gif'. */ static struct image_type gif_type = @@ -7032,6 +7111,7 @@ static struct image_type gif_type = gif_image_p, gif_load, gif_clear_image, + init_gif_functions, NULL }; @@ -7090,11 +7170,11 @@ DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc)); DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *)); static int -init_gif_functions (Lisp_Object libraries) +init_gif_functions (void) { HMODULE library; - if (!(library = w32_delayed_load (libraries, Qgif))) + if (!(library = w32_delayed_load (Qgif))) return 0; LOAD_IMGLIB_FN (library, DGifCloseFile); @@ -7514,6 +7594,12 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} }; +#ifdef HAVE_NTGUI +static int init_imagemagick_functions (void); +#else +#define init_imagemagick_functions NULL +#endif + /* Structure describing the image type for any image handled via ImageMagick. */ @@ -7523,6 +7609,7 @@ static struct image_type imagemagick_type = imagemagick_image_p, imagemagick_load, imagemagick_clear_image, + init_imagemagick_functions, NULL }; @@ -7576,7 +7663,7 @@ imagemagick_error (MagickWand *wand) description = MagickGetException (wand, &severity); image_error ("ImageMagick error: %s", - make_string (description, strlen (description)), + build_string (description), Qnil); description = (char *) MagickRelinquishMemory (description); } @@ -7598,19 +7685,14 @@ imagemagick_load_image (struct frame *f, struct image *img, unsigned char *contents, unsigned int size, char *filename) { - size_t width; - size_t height; - + size_t width, height; MagickBooleanType status; - XImagePtr ximg; - int x; - int y; - - MagickWand *image_wand; - MagickWand *ping_wand; + int x, y; + MagickWand *image_wand; + MagickWand *ping_wand; PixelIterator *iterator; - PixelWand **pixels; + PixelWand **pixels, *bg_wand = NULL; MagickPixelPacket pixel; Lisp_Object image; Lisp_Object value; @@ -7619,10 +7701,6 @@ imagemagick_load_image (struct frame *f, struct image *img, int desired_width, desired_height; double rotation; int pixelwidth; - ImageInfo *image_info; - ExceptionInfo *exception; - Image * im_image; - /* Handle image index for image types who can contain more than one image. Interface :index is same as for GIF. First we "ping" the image to see how @@ -7636,14 +7714,9 @@ imagemagick_load_image (struct frame *f, struct image *img, ping_wand = NewMagickWand (); /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */ - if (filename != NULL) - { - status = MagickPingImage (ping_wand, filename); - } - else - { - status = MagickPingImageBlob (ping_wand, contents, size); - } + status = filename + ? MagickPingImage (ping_wand, filename) + : MagickPingImageBlob (ping_wand, contents, size); if (status == MagickFalse) { @@ -7652,7 +7725,7 @@ imagemagick_load_image (struct frame *f, struct image *img, return 0; } - if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand))) + if (ino < 0 || ino >= MagickGetNumberImages (ping_wand)) { image_error ("Invalid image number `%s' in image `%s'", image, img->spec); @@ -7669,39 +7742,46 @@ imagemagick_load_image (struct frame *f, struct image *img, DestroyMagickWand (ping_wand); /* Now we know how many images are inside the file. If it's not a - bundle, the number is one. */ + bundle, the number is one. Load the image data. */ - if (filename != NULL) - { - image_info = CloneImageInfo ((ImageInfo *) NULL); - (void) strcpy (image_info->filename, filename); - image_info->number_scenes = 1; - image_info->scene = ino; - exception = AcquireExceptionInfo (); - - im_image = ReadImage (image_info, exception); - DestroyExceptionInfo (exception); + image_wand = NewMagickWand (); - if (im_image == NULL) - goto imagemagick_no_wand; - image_wand = NewMagickWandFromImage (im_image); - DestroyImage (im_image); - } - else + if ((filename + ? MagickReadImage (image_wand, filename) + : MagickReadImageBlob (image_wand, contents, size)) + == MagickFalse) { - image_wand = NewMagickWand (); - if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse) - { - imagemagick_error (image_wand); - goto imagemagick_error; - } + imagemagick_error (image_wand); + goto imagemagick_error; } + /* Retrieve the frame's background color, for use later. */ + { + XColor bgcolor; + Lisp_Object specified_bg; + + specified_bg = image_spec_value (img->spec, QCbackground, NULL); + if (!STRINGP (specified_bg) + || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0)) + { +#ifndef HAVE_NS + bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f); + x_query_color (f, &bgcolor); +#else + ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1); +#endif + } + + bg_wand = NewPixelWand (); + PixelSetRed (bg_wand, (double) bgcolor.red / 65535); + PixelSetGreen (bg_wand, (double) bgcolor.green / 65535); + PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535); + } + /* If width and/or height is set in the display spec assume we want to scale to those values. If either h or w is unspecified, the unspecified should be calculated from the specified to preserve aspect ratio. */ - value = image_spec_value (img->spec, QCwidth, NULL); desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); value = image_spec_value (img->spec, QCheight, NULL); @@ -7767,13 +7847,8 @@ imagemagick_load_image (struct frame *f, struct image *img, value = image_spec_value (img->spec, QCrotation, NULL); if (FLOATP (value)) { - PixelWand* background = NewPixelWand (); - PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ - rotation = extract_float (value); - - status = MagickRotateImage (image_wand, background, rotation); - DestroyPixelWand (background); + status = MagickRotateImage (image_wand, bg_wand, rotation); if (status == MagickFalse) { image_error ("Imagemagick image rotate failed", Qnil, Qnil); @@ -7787,6 +7862,22 @@ imagemagick_load_image (struct frame *f, struct image *img, height = MagickGetImageHeight (image_wand); width = MagickGetImageWidth (image_wand); + /* Set the canvas background color to the frame or specified + background, and flatten the image. Note: as of ImageMagick + 6.6.0, SVG image transparency is not handled properly + (e.g. etc/images/splash.svg shows a white background always). */ + { + MagickWand *new_wand; + MagickSetImageBackgroundColor (image_wand, bg_wand); +#ifdef HAVE_MAGICKMERGEIMAGELAYERS + new_wand = MagickMergeImageLayers (image_wand, MergeLayer); +#else + new_wand = MagickFlattenImages (image_wand); +#endif + DestroyMagickWand (image_wand); + image_wand = new_wand; + } + if (! (width <= INT_MAX && height <= INT_MAX && check_image_size (f, width, height))) { @@ -7799,7 +7890,50 @@ imagemagick_load_image (struct frame *f, struct image *img, init_color_table (); - if (imagemagick_render_type == 0) +#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS + if (imagemagick_render_type != 0) + { + /* Magicexportimage is normally faster than pixelpushing. This + method is also well tested. Some aspects of this method are + ad-hoc and needs to be more researched. */ + int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/ + const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/ + /* Try to create a x pixmap to hold the imagemagick pixmap. */ + if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, + &ximg, &img->pixmap)) + { +#ifdef COLOR_TABLE_SUPPORT + free_color_table (); +#endif + image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil); + goto imagemagick_error; + } + + /* Oddly, the below code doesn't seem to work:*/ + /* switch(ximg->bitmap_unit){ */ + /* case 8: */ + /* pixelwidth=CharPixel; */ + /* break; */ + /* case 16: */ + /* pixelwidth=ShortPixel; */ + /* break; */ + /* case 32: */ + /* pixelwidth=LongPixel; */ + /* break; */ + /* } */ + /* + Here im just guessing the format of the bitmap. + happens to work fine for: + - bw djvu images + on rgb display. + seems about 3 times as fast as pixel pushing(not carefully measured) + */ + pixelwidth = CharPixel; /*??? TODO figure out*/ + MagickExportImagePixels (image_wand, 0, 0, width, height, + exportdepth, pixelwidth, ximg->data); + } + else +#endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */ { size_t image_height; @@ -7849,59 +7983,6 @@ imagemagick_load_image (struct frame *f, struct image *img, } DestroyPixelIterator (iterator); } - else /* imagemagick_render_type != 0 */ - { - /* Magicexportimage is normally faster than pixelpushing. This - method is also well tested. Some aspects of this method are - ad-hoc and needs to be more researched. */ - int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ - const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ - /* Try to create a x pixmap to hold the imagemagick pixmap. */ - if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, - &ximg, &img->pixmap)) - { -#ifdef COLOR_TABLE_SUPPORT - free_color_table (); -#endif - image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil); - goto imagemagick_error; - } - - - /* Oddly, the below code doesn't seem to work:*/ - /* switch(ximg->bitmap_unit){ */ - /* case 8: */ - /* pixelwidth=CharPixel; */ - /* break; */ - /* case 16: */ - /* pixelwidth=ShortPixel; */ - /* break; */ - /* case 32: */ - /* pixelwidth=LongPixel; */ - /* break; */ - /* } */ - /* - Here im just guessing the format of the bitmap. - happens to work fine for: - - bw djvu images - on rgb display. - seems about 3 times as fast as pixel pushing(not carefully measured) - */ - pixelwidth = CharPixel;/*??? TODO figure out*/ -#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS - MagickExportImagePixels (image_wand, - 0, 0, - width, height, - exportdepth, - pixelwidth, - /*&(img->pixmap));*/ - ximg->data); -#else - image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!", - Qnil, Qnil); -#endif - } - #ifdef COLOR_TABLE_SUPPORT /* Remember colors allocated for this image. */ @@ -7909,7 +7990,6 @@ imagemagick_load_image (struct frame *f, struct image *img, free_color_table (); #endif /* COLOR_TABLE_SUPPORT */ - img->width = width; img->height = height; @@ -7918,9 +7998,10 @@ imagemagick_load_image (struct frame *f, struct image *img, x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); - /* Final cleanup. image_wand should be the only resource left. */ DestroyMagickWand (image_wand); + if (bg_wand) DestroyPixelWand (bg_wand); + /* `MagickWandTerminus' terminates the imagemagick environment. */ MagickWandTerminus (); @@ -7928,7 +8009,8 @@ imagemagick_load_image (struct frame *f, struct image *img, imagemagick_error: DestroyMagickWand (image_wand); - imagemagick_no_wand: + if (bg_wand) DestroyPixelWand (bg_wand); + MagickWandTerminus (); /* TODO more cleanup. */ image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); @@ -7987,15 +8069,21 @@ their descriptions (http://www.imagemagick.org/script/formats.php). You can also try the shell command: `identify -list format'. Note that ImageMagick recognizes many file-types that Emacs does not -recognize as images, such as C. See `imagemagick-types-inhibit'. */) +recognize as images, such as C. See `imagemagick-types-enable' +and `imagemagick-types-inhibit'. */) (void) { Lisp_Object typelist = Qnil; size_t numf = 0; ExceptionInfo ex; - char **imtypes = GetMagickList ("*", &numf, &ex); + char **imtypes; size_t i; Lisp_Object Qimagemagicktype; + + GetExceptionInfo(&ex); + imtypes = GetMagickList ("*", &numf, &ex); + DestroyExceptionInfo(&ex); + for (i = 0; i < numf; i++) { Qimagemagicktype = intern (imtypes[i]); @@ -8060,22 +8148,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 (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 = { - /* 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 }; @@ -8124,14 +8213,14 @@ DEF_IMGLIB_FN (void, g_error_free); Lisp_Object Qgdk_pixbuf, Qglib, Qgobject; static int -init_svg_functions (Lisp_Object libraries) +init_svg_functions (void) { HMODULE library, gdklib, glib, gobject; - if (!(glib = w32_delayed_load (libraries, Qglib)) - || !(gobject = w32_delayed_load (libraries, Qgobject)) - || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf)) - || !(library = w32_delayed_load (libraries, Qsvg))) + if (!(glib = w32_delayed_load (Qglib)) + || !(gobject = w32_delayed_load (Qgobject)) + || !(gdklib = w32_delayed_load (Qgdk_pixbuf)) + || !(library = w32_delayed_load (Qsvg))) return 0; LOAD_IMGLIB_FN (library, rsvg_handle_new); @@ -8463,6 +8552,7 @@ static struct image_type gs_type = gs_image_p, gs_load, gs_clear_image, + NULL, NULL }; @@ -8506,7 +8596,7 @@ gs_image_p (Lisp_Object object) if (ASIZE (tem) != 4) return 0; for (i = 0; i < 4; ++i) - if (!INTEGERP (XVECTOR (tem)->contents[i])) + if (!INTEGERP (AREF (tem, i))) return 0; } else @@ -8550,16 +8640,16 @@ gs_load (struct frame *f, struct image *img) img->height = in_height; /* Create the pixmap. */ - xassert (img->pixmap == NO_PIXMAP); + eassert (img->pixmap == NO_PIXMAP); if (x_check_image_size (0, img->width, img->height)) { /* Only W32 version did BLOCK_INPUT here. ++kfs */ - BLOCK_INPUT; + block_input (); img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), img->width, img->height, DefaultDepthOfScreen (FRAME_X_SCREEN (f))); - UNBLOCK_INPUT; + unblock_input (); } if (!img->pixmap) @@ -8574,13 +8664,13 @@ gs_load (struct frame *f, struct image *img) don't either. Let the Lisp loader use `unwind-protect' instead. */ printnum1 = FRAME_X_WINDOW (f); printnum2 = img->pixmap; - sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); - window_and_pixmap_id = build_string (buffer); + window_and_pixmap_id + = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2); printnum1 = FRAME_FOREGROUND_PIXEL (f); printnum2 = FRAME_BACKGROUND_PIXEL (f); - sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); - pixel_colors = build_string (buffer); + pixel_colors + = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2); XSETFRAME (frame, f); loader = image_spec_value (img->spec, QCloader, NULL); @@ -8621,7 +8711,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) /* Kill the GS process. We should have found PIXMAP in the image cache and its image should contain a process object. */ img = c->images[i]; - xassert (PROCESSP (img->lisp_data)); + eassert (PROCESSP (img->lisp_data)); Fkill_process (img->lisp_data, Qnil); img->lisp_data = Qnil; @@ -8635,7 +8725,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) { XImagePtr ximg; - BLOCK_INPUT; + block_input (); /* Try to get an XImage for img->pixmep. */ ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, @@ -8678,15 +8768,15 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) image_error ("Cannot get X image of `%s'; colors will not be freed", img->spec, Qnil); - UNBLOCK_INPUT; + unblock_input (); } #endif /* HAVE_X_WINDOWS */ /* Now that we have the pixmap, compute mask and transform the image if requested. */ - BLOCK_INPUT; + block_input (); postprocess_image (f, img); - UNBLOCK_INPUT; + unblock_input (); } #endif /* HAVE_GHOSTSCRIPT */ @@ -8696,7 +8786,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) Tests ***********************************************************************/ -#if GLYPH_DEBUG +#ifdef GLYPH_DEBUG DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0, doc: /* Value is non-nil if SPEC is a valid image specification. */) @@ -8718,87 +8808,79 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") return make_number (id); } -#endif /* GLYPH_DEBUG != 0 */ +#endif /* GLYPH_DEBUG */ /*********************************************************************** 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, +DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0, doc: /* Initialize image library implementing image type TYPE. Return non-nil if TYPE is a supported image type. -Image types pbm and xbm are prebuilt; other types are loaded here. -Libraries to load are specified in alist LIBRARIES (usually, the value -of `dynamic-library-alist', which see). */) - (Lisp_Object type, Lisp_Object libraries) +If image libraries are loaded dynamically (currently only the case on +MS-Windows), load the library for TYPE if it is not yet loaded, using +the library file(s) specified by `dynamic-library-alist'. */) + (Lisp_Object type) { -#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) ? 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) +{ /* 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); + + if (EQ (type, Qxbm)) + return define_image_type (&xbm_type); #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); #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); #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); #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); #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); #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); #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); #endif #ifdef HAVE_GHOSTSCRIPT if (EQ (type, Qpostscript)) - return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); + return define_image_type (&gs_type); #endif - /* If the type is not recognized, avoid testing it ever again. */ - CACHE_IMAGE_TYPE (type, Qnil); - return Qnil; + return NULL; } void @@ -8829,15 +8911,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"); @@ -8881,6 +8954,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); @@ -8932,7 +9011,7 @@ non-numeric, there is no explicit limit on the size of images. */); defsubr (&Simage_mask_p); defsubr (&Simage_metadata); -#if GLYPH_DEBUG +#ifdef GLYPH_DEBUG defsubr (&Simagep); defsubr (&Slookup_image); #endif @@ -8971,8 +9050,3 @@ The options are: #endif } - -void -init_image (void) -{ -}