X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/b7e0ef72d0ac61b5d3ef06a3f565695c75ec2540..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/image.c diff --git a/src/image.c b/src/image.c index 6691cfc8a1..7fa28840c1 100644 --- a/src/image.c +++ b/src/image.c @@ -1,6 +1,6 @@ /* Functions for image support on window system. -Copyright (C) 1989, 1992-2013 Free Software Foundation, Inc. +Copyright (C) 1989, 1992-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -21,13 +21,11 @@ along with GNU Emacs. If not, see . */ #include "sysstdio.h" #include -#ifdef HAVE_PNG -#if defined HAVE_LIBPNG_PNG_H -# include -#else +/* Include this before including to work around bugs with + older libpng; see Bug#17429. */ +#if defined HAVE_PNG && !defined HAVE_NS # include #endif -#endif #include #include @@ -87,11 +85,12 @@ typedef struct w32_bitmap_record Bitmap_Record; #define x_defined_color w32_defined_color #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits) -/* Versions of libpng and libgif that we were compiled with, or -1 if - no PNG/GIF support was compiled in. This is tested by w32-win.el - to correctly set up the alist used to search for the respective - image libraries. */ -Lisp_Object Qlibpng_version, Qlibgif_version; +/* Versions of libpng, libgif, and libjpeg that we were compiled with, + or -1 if no PNG/GIF support was compiled in. This is tested by + w32-win.el to correctly set up the alist used to search for the + respective image libraries. */ +Lisp_Object Qlibpng_version, Qlibgif_version, Qlibjpeg_version; + #endif /* HAVE_NTGUI */ #ifdef HAVE_NS @@ -159,6 +158,7 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) /* Functions to access the contents of a bitmap, given an id. */ +#ifdef HAVE_X_WINDOWS static int x_bitmap_height (struct frame *f, ptrdiff_t id) { @@ -170,6 +170,7 @@ x_bitmap_width (struct frame *f, ptrdiff_t id) { return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].width; } +#endif #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) ptrdiff_t @@ -263,7 +264,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi #ifdef HAVE_X_WINDOWS dpyinfo->bitmaps[id - 1].pixmap = bitmap; - dpyinfo->bitmaps[id - 1].have_mask = 0; + dpyinfo->bitmaps[id - 1].have_mask = false; dpyinfo->bitmaps[id - 1].depth = 1; #endif /* HAVE_X_WINDOWS */ @@ -326,7 +327,9 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) } /* Search bitmap-file-path for the file, if appropriate. */ - if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK)) < 0) + if (openp (Vx_bitmap_file_path, file, Qnil, &found, + make_number (R_OK), false) + < 0) return -1; filename = SSDATA (found); @@ -338,7 +341,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) id = x_allocate_bitmap_record (f); dpyinfo->bitmaps[id - 1].pixmap = bitmap; - dpyinfo->bitmaps[id - 1].have_mask = 0; + dpyinfo->bitmaps[id - 1].have_mask = false; dpyinfo->bitmaps[id - 1].refcount = 1; dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); dpyinfo->bitmaps[id - 1].depth = 1; @@ -514,7 +517,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) width, height); XFreeGC (FRAME_X_DISPLAY (f), gc); - dpyinfo->bitmaps[id - 1].have_mask = 1; + dpyinfo->bitmaps[id - 1].have_mask = true; dpyinfo->bitmaps[id - 1].mask = mask; XDestroyImage (ximg); @@ -995,6 +998,11 @@ free_image (struct frame *f, struct image *img) c->images[img->id] = NULL; + /* Windows NT redefines 'free', but in this file, we need to + avoid the redefinition. */ +#ifdef WINDOWSNT +#undef free +#endif /* Free resources, then free IMG. */ img->type->free (f, img); xfree (img); @@ -1228,7 +1236,23 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D return img->background_transparent; } - +#if defined (HAVE_PNG) || defined (HAVE_NS) \ + || defined (HAVE_IMAGEMAGICK) || defined (HAVE_RSVG) + +/* Store F's background color into *BGCOLOR. */ +static void +x_query_frame_background_color (struct frame *f, XColor *bgcolor) +{ +#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 +} + +#endif /* HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG */ + /*********************************************************************** Helper functions for X image types ***********************************************************************/ @@ -1520,7 +1544,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) clear_current_matrices (fr); } - ++windows_or_buffers_changed; + windows_or_buffers_changed = 19; } unblock_input (); @@ -1798,37 +1822,6 @@ cache_image (struct frame *f, struct image *img) img->prev = NULL; c->buckets[i] = img; } - - -/* Call FN on every image in the image cache of frame F. Used to mark - Lisp Objects in the image cache. */ - -/* Mark Lisp objects in image IMG. */ - -static void -mark_image (struct image *img) -{ - mark_object (img->spec); - mark_object (img->dependencies); - - if (!NILP (img->lisp_data)) - mark_object (img->lisp_data); -} - - -void -mark_image_cache (struct image_cache *c) -{ - if (c) - { - ptrdiff_t i; - for (i = 0; i < c->used; ++i) - if (c->images[i]) - mark_image (c->images[i]); - } -} - - /*********************************************************************** X / NS / W32 support code @@ -1927,7 +1920,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, } /* Allocate image raster. */ - (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); + (*ximg)->data = xmalloc_atomic ((*ximg)->bytes_per_line * height); /* Allocate a pixmap of the same size. */ *pixmap = XCreatePixmap (display, window, width, height, depth); @@ -2016,6 +2009,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, XSETINT (errcode, err); image_error ("Unable to create bitmap, error code %d", errcode, Qnil); x_destroy_x_image (*ximg); + *ximg = NULL; return 0; } @@ -2241,7 +2235,7 @@ x_find_image_file (Lisp_Object file) Vx_bitmap_file_path); /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ - fd = openp (search_path, file, Qnil, &file_found, Qnil); + fd = openp (search_path, file, Qnil, &file_found, Qnil, false); if (fd == -1) file_found = Qnil; @@ -2269,7 +2263,7 @@ slurp_file (char *file, ptrdiff_t *size) if (fp) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); record_unwind_protect_ptr (fclose_unwind, fp); if (fstat (fileno (fp), &st) == 0 @@ -2288,7 +2282,7 @@ slurp_file (char *file, ptrdiff_t *size) } } - unbind_to (count, Qnil); + dynwind_end (); } return buf; @@ -2794,7 +2788,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 = xmalloc (nbytes); + p = *data = xmalloc_atomic (nbytes); if (v10) { @@ -3025,13 +3019,13 @@ xbm_load (struct frame *f, struct image *img) if (STRINGP (line)) memcpy (p, SDATA (line), nbytes); else - memcpy (p, XBOOL_VECTOR (line)->data, nbytes); + memcpy (p, bool_vector_data (line), nbytes); } } else if (STRINGP (data)) bits = SSDATA (data); else - bits = (char *) XBOOL_VECTOR (data)->data; + bits = (char *) bool_vector_data (data); #ifdef HAVE_NTGUI { @@ -3445,7 +3439,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits) id = x_allocate_bitmap_record (f); dpyinfo->bitmaps[id - 1].pixmap = bitmap; - dpyinfo->bitmaps[id - 1].have_mask = 1; + dpyinfo->bitmaps[id - 1].have_mask = true; dpyinfo->bitmaps[id - 1].mask = mask; dpyinfo->bitmaps[id - 1].file = NULL; dpyinfo->bitmaps[id - 1].height = attrs.height; @@ -3589,6 +3583,12 @@ xpm_load (struct frame *f, struct image *img) } #ifdef HAVE_NTGUI +#ifdef WINDOWSNT + /* FILE is encoded in UTF-8, but image libraries on Windows + support neither UTF-8 nor UTF-16 encoded file names. So we + need to re-encode it in ANSI. */ + file = ansi_encode_filename (file); +#endif /* XpmReadFileToPixmap is not available in the Windows port of libxpm. But XpmReadFileToImage almost does what we want. */ rc = fn_XpmReadFileToImage (&hdc, SDATA (file), @@ -3687,7 +3687,8 @@ xpm_load (struct frame *f, struct image *img) #endif /* HAVE_NTGUI */ /* Remember allocated colors. */ - img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors); + img->colors = xnmalloc_atomic (attrs.nalloc_pixels, + sizeof *img->colors); img->ncolors = attrs.nalloc_pixels; for (i = 0; i < attrs.nalloc_pixels; ++i) { @@ -3943,9 +3944,7 @@ xpm_str_to_color_key (const char *s) { int i; - for (i = 0; - i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0]; - i++) + for (i = 0; i < ARRAYELTS (xpm_color_key_strings); i++) if (strcmp (xpm_color_key_strings[i], s) == 0) return i; return -1; @@ -3967,7 +3966,7 @@ xpm_load_image (struct frame *f, Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int); Lisp_Object frame, color_symbols, color_table; int best_key; - bool have_mask = 0; + bool have_mask = false; XImagePtr ximg = NULL, mask_img = NULL; #define match() \ @@ -4139,7 +4138,7 @@ xpm_load_image (struct frame *f, #ifndef HAVE_NS XPutPixel (mask_img, x, y, (!EQ (color_val, Qt) ? PIX_MASK_DRAW - : (have_mask = 1, PIX_MASK_RETAIN))); + : (have_mask = true, PIX_MASK_RETAIN))); #else if (EQ (color_val, Qt)) ns_set_alpha (ximg, x, y, 0); @@ -4484,7 +4483,7 @@ colors_in_color_table (int *n) } else { - colors = xmalloc (ct_colors_allocated * sizeof *colors); + colors = xmalloc_atomic (ct_colors_allocated * sizeof *colors); *n = ct_colors_allocated; for (i = j = 0; i < CT_SIZE; ++i) @@ -5105,6 +5104,27 @@ pbm_image_p (Lisp_Object object) } +/* Get next char skipping comments in Netpbm header. Returns -1 at + end of input. */ + +static int +pbm_next_char (unsigned char **s, unsigned char *end) +{ + int c = -1; + + while (*s < end && (c = *(*s)++, c == '#')) + { + /* Skip to the next line break. */ + while (*s < end && (c = *(*s)++, c != '\n' && c != '\r')) + ; + + c = -1; + } + + return c; +} + + /* Scan a decimal number from *S and return it. Advance *S while reading the number. END is the end of the string. Value is -1 at end of input. */ @@ -5114,28 +5134,16 @@ pbm_scan_number (unsigned char **s, unsigned char *end) { int c = 0, val = -1; - while (*s < end) - { - /* Skip white-space. */ - while (*s < end && (c = *(*s)++, c_isspace (c))) - ; + /* Skip white-space. */ + while ((c = pbm_next_char (s, end)) != -1 && c_isspace (c)) + ; - if (c == '#') - { - /* Skip comment to end of line. */ - while (*s < end && (c = *(*s)++, c != '\n')) - ; - } - else if (c_isdigit (c)) - { - /* Read decimal number. */ - val = c - '0'; - while (*s < end && (c = *(*s)++, c_isdigit (c))) - val = 10 * val + c - '0'; - break; - } - else - break; + if (c_isdigit (c)) + { + /* Read decimal number. */ + val = c - '0'; + while ((c = pbm_next_char (s, end)) != -1 && c_isdigit (c)) + val = 10 * val + c - '0'; } return val; @@ -5197,6 +5205,7 @@ pbm_load (struct frame *f, struct image *img) image_error ("Not a PBM image: `%s'", img->spec, Qnil); error: xfree (contents); + img->pixmap = NO_PIXMAP; return 0; } @@ -5486,7 +5495,7 @@ png_image_p (Lisp_Object object) #endif /* HAVE_PNG || HAVE_NS */ -#ifdef HAVE_PNG +#if defined HAVE_PNG && !defined HAVE_NS #ifdef WINDOWSNT /* PNG library details. */ @@ -5518,7 +5527,7 @@ DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop)); DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp)); #if (PNG_LIBPNG_VER >= 10500) -DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int)); +DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int)) PNG_NORETURN; DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t)); #endif /* libpng version >= 1.5 */ @@ -5590,24 +5599,26 @@ init_png_functions (void) #endif /* WINDOWSNT */ -/* 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 +/* Fast implementations of setjmp and longjmp. Although setjmp and longjmp + will do, POSIX _setjmp and _longjmp (if available) are often faster. + Do not use sys_setjmp, as PNG supports only jmp_buf. + It's OK if the longjmp substitute restores the signal mask. */ +#ifdef HAVE__SETJMP +# define FAST_SETJMP(j) _setjmp (j) +# define FAST_LONGJMP _longjmp +#else +# define FAST_SETJMP(j) setjmp (j) +# define FAST_LONGJMP longjmp #endif -#if (PNG_LIBPNG_VER < 10500) -#define PNG_LONGJMP(ptr) (_longjmp ((ptr)->jmpbuf, 1)) +#if PNG_LIBPNG_VER < 10500 +#define PNG_LONGJMP(ptr) FAST_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_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, FAST_LONGJMP, sizeof (jmp_buf))) #endif /* Error and warning handlers installed when the PNG library @@ -5792,7 +5803,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) /* Set error jump-back. We come back here when the PNG library detects an error. */ - if (_setjmp (PNG_JMPBUF (png_ptr))) + if (FAST_SETJMP (PNG_JMPBUF (png_ptr))) { error: if (c->png_ptr) @@ -5862,43 +5873,23 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) /* png_color_16 *image_bg; */ Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); - int shift = (bit_depth == 16) ? 0 : 8; + XColor color; - if (STRINGP (specified_bg)) + /* If the user specified a color, try to use it; if not, use the + current frame background, ignoring any default background + color set by the image. */ + if (STRINGP (specified_bg) + ? x_defined_color (f, SSDATA (specified_bg), &color, false) + : (x_query_frame_background_color (f, &color), true)) /* The user specified `:background', use that. */ { - XColor color; - if (x_defined_color (f, SSDATA (specified_bg), &color, 0)) - { - png_color_16 user_bg; - - memset (&user_bg, 0, sizeof user_bg); - user_bg.red = color.red >> shift; - user_bg.green = color.green >> shift; - user_bg.blue = color.blue >> shift; - - fn_png_set_background (png_ptr, &user_bg, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - } - } - else - { - /* We use the current frame background, ignoring any default - background color set by the image. */ -#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) - XColor color; - png_color_16 frame_background; - - color.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &color); + int shift = bit_depth == 16 ? 0 : 8; + png_color_16 bg = { 0 }; + bg.red = color.red >> shift; + bg.green = color.green >> shift; + bg.blue = color.blue >> shift; - memset (&frame_background, 0, sizeof frame_background); - frame_background.red = color.red >> shift; - frame_background.green = color.green >> shift; - frame_background.blue = color.blue >> shift; -#endif /* HAVE_X_WINDOWS */ - - fn_png_set_background (png_ptr, &frame_background, + fn_png_set_background (png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } @@ -5921,8 +5912,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes) memory_full (SIZE_MAX); - c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height); - c->rows = rows = xmalloc (height * sizeof *rows); + c->pixels = pixels = xmalloc_atomic (sizeof *pixels * row_bytes * height); + c->rows = rows = xmalloc_atomic (height * sizeof *rows); for (i = 0; i < height; ++i) rows[i] = pixels + i * row_bytes; @@ -6040,9 +6031,8 @@ png_load (struct frame *f, struct image *img) return png_load_body (f, img, &c); } -#else /* HAVE_PNG */ +#elif defined HAVE_NS -#ifdef HAVE_NS static bool png_load (struct frame *f, struct image *img) { @@ -6050,10 +6040,8 @@ png_load (struct frame *f, struct image *img) image_spec_value (img->spec, QCfile, NULL), image_spec_value (img->spec, QCdata, NULL)); } -#endif /* HAVE_NS */ - -#endif /* !HAVE_PNG */ +#endif /* HAVE_NS */ @@ -6240,9 +6228,6 @@ struct my_jpeg_error_mgr MY_JPEG_INVALID_IMAGE_SIZE, MY_JPEG_CANNOT_CREATE_X } failure_code; -#ifdef lint - FILE *fp; -#endif }; @@ -6447,7 +6432,6 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp) src->mgr.next_input_byte = NULL; } - /* Load image IMG for use on frame F. Patterned after example.c from the JPEG lib. */ @@ -6457,7 +6441,8 @@ jpeg_load_body (struct frame *f, struct image *img, { Lisp_Object file, specified_file; Lisp_Object specified_data; - FILE *fp = NULL; + /* The 'volatile' silences a bogus diagnostic; see GCC bug 54561. */ + FILE * IF_LINT (volatile) fp = NULL; JSAMPARRAY buffer; int row_stride, x, y; XImagePtr ximg = NULL; @@ -6490,8 +6475,6 @@ jpeg_load_body (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. */ mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub); @@ -6530,9 +6513,6 @@ jpeg_load_body (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 (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo); @@ -6958,6 +6938,9 @@ tiff_load (struct frame *f, struct image *img) image_error ("Cannot find image file `%s'", specified_file, Qnil); return 0; } +#ifdef WINDOWSNT + file = ansi_encode_filename (file); +#endif /* Try to open the image file. */ tiff = fn_TIFFOpen (SSDATA (file), "r"); @@ -7031,7 +7014,7 @@ tiff_load (struct frame *f, struct image *img) return 0; } - buf = xmalloc (sizeof *buf * width * height); + buf = xmalloc_atomic (sizeof *buf * width * height); rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); @@ -7237,7 +7220,11 @@ gif_image_p (Lisp_Object object) #ifdef WINDOWSNT /* GIF library details. */ +#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR) +DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *, int *)); +#else DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *)); +#endif DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *)); #if GIFLIB_MAJOR < 5 DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc)); @@ -7307,6 +7294,22 @@ gif_read_from_memory (GifFileType *file, GifByteType *buf, int len) return len; } +static int +gif_close (GifFileType *gif, int *err) +{ + int retval; + +#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR) + retval = fn_DGifCloseFile (gif, err); +#else + retval = fn_DGifCloseFile (gif); +#if GIFLIB_MAJOR >= 5 + if (err) + *err = gif->Error; +#endif +#endif + return retval; +} /* Load GIF image IMG for use on frame F. Value is true if successful. */ @@ -7331,9 +7334,7 @@ gif_load (struct frame *f, struct image *img) Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); unsigned long bgcolor = 0; EMACS_INT idx; -#if GIFLIB_MAJOR >= 5 int gif_err; -#endif if (NILP (specified_data)) { @@ -7343,6 +7344,9 @@ gif_load (struct frame *f, struct image *img) image_error ("Cannot find image file `%s'", specified_file, Qnil); return 0; } +#ifdef WINDOWSNT + file = ansi_encode_filename (file); +#endif /* Open the GIF file. */ #if GIFLIB_MAJOR < 5 @@ -7398,7 +7402,7 @@ gif_load (struct frame *f, struct image *img) if (!check_image_size (f, gif->SWidth, gif->SHeight)) { image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } @@ -7407,7 +7411,7 @@ gif_load (struct frame *f, struct image *img) if (rc == GIF_ERROR || gif->ImageCount <= 0) { image_error ("Error reading `%s'", img->spec, Qnil); - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } @@ -7419,7 +7423,7 @@ gif_load (struct frame *f, struct image *img) { image_error ("Invalid image number `%s' in image `%s'", image_number, img->spec); - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } } @@ -7437,7 +7441,7 @@ gif_load (struct frame *f, struct image *img) if (!check_image_size (f, width, height)) { image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } @@ -7455,7 +7459,7 @@ gif_load (struct frame *f, struct image *img) && 0 <= subimg_left && subimg_left <= width - subimg_width)) { image_error ("Subimage does not fit in image", Qnil, Qnil); - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } } @@ -7463,7 +7467,7 @@ gif_load (struct frame *f, struct image *img) /* Create the X image and pixmap. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) { - fn_DGifCloseFile (gif); + gif_close (gif, NULL); return 0; } @@ -7562,7 +7566,7 @@ gif_load (struct frame *f, struct image *img) } /* Apply the pixel values. */ - if (gif->SavedImages[j].ImageDesc.Interlace) + if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace) { int row, pass; @@ -7634,7 +7638,18 @@ gif_load (struct frame *f, struct image *img) Fcons (make_number (gif->ImageCount), img->lisp_data)); - fn_DGifCloseFile (gif); + if (gif_close (gif, &gif_err) == GIF_ERROR) + { +#if 5 <= GIFLIB_MAJOR + char *error_text = fn_GifErrorString (gif_err); + + if (error_text) + image_error ("Error closing `%s': %s", + img->spec, build_string (error_text)); +#else + image_error ("Error closing `%s'", img->spec, Qnil); +#endif + } /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) @@ -7882,7 +7897,7 @@ imagemagick_error (MagickWand *wand) image_error ("ImageMagick error: %s", build_string (description), Qnil); - description = (char *) MagickRelinquishMemory (description); + MagickRelinquishMemory (description); } /* Possibly give ImageMagick some extra help to determine the image @@ -8083,7 +8098,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino) { /* Sanity check. This shouldn't happen, but apparently also does in some pictures. */ - if (x + source_left > dest_width) + if (x + source_left > dest_width - 1) break; /* Normally we only copy over non-transparent pixels, but if the disposal method is "Background", then we @@ -8208,14 +8223,7 @@ imagemagick_load_image (struct frame *f, struct image *img, 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 - } + x_query_frame_background_color (f, &bgcolor); bg_wand = NewPixelWand (); PixelSetRed (bg_wand, (double) bgcolor.red / 65535); @@ -8367,6 +8375,7 @@ imagemagick_load_image (struct frame *f, struct image *img, #endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */ { size_t image_height; + MagickRealType color_scale = 65535.0 / QuantumRange; /* Try to create a x pixmap to hold the imagemagick pixmap. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, @@ -8407,9 +8416,9 @@ imagemagick_load_image (struct frame *f, struct image *img, PixelGetMagickColor (pixels[x], &pixel); XPutPixel (ximg, x, y, lookup_rgb_color (f, - pixel.red, - pixel.green, - pixel.blue)); + color_scale * pixel.red, + color_scale * pixel.green, + color_scale * pixel.blue)); } } DestroyPixelIterator (iterator); @@ -8469,6 +8478,9 @@ imagemagick_load (struct frame *f, struct image *img) image_error ("Cannot find image file `%s'", file_name, Qnil); return 0; } +#ifdef WINDOWSNT + file = ansi_encode_filename (file); +#endif success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file)); } /* Else its not a file, its a lisp object. Load the image from a @@ -8507,7 +8519,6 @@ and `imagemagick-types-inhibit'. */) ExceptionInfo ex; char **imtypes; size_t i; - Lisp_Object Qimagemagicktype; GetExceptionInfo(&ex); imtypes = GetMagickList ("*", &numf, &ex); @@ -8515,9 +8526,12 @@ and `imagemagick-types-inhibit'. */) for (i = 0; i < numf; i++) { - Qimagemagicktype = intern (imtypes[i]); - typelist = Fcons (Qimagemagicktype, typelist); + Lisp_Object imagemagicktype = intern (imtypes[i]); + typelist = Fcons (imagemagicktype, typelist); + imtypes[i] = MagickRelinquishMemory (imtypes[i]); } + + MagickRelinquishMemory (imtypes); return Fnreverse (typelist); } @@ -8625,7 +8639,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions, (RsvgHandle *, RsvgDimensionDat DEF_IMGLIB_FN (gboolean, rsvg_handle_write, (RsvgHandle *, const guchar *, gsize, GError **)); DEF_IMGLIB_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **)); DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *)); -DEF_IMGLIB_FN (void *, rsvg_handle_set_size_callback, (RsvgHandle *, RsvgSizeFunc, gpointer, GDestroyNotify)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *)); @@ -8647,13 +8660,18 @@ Lisp_Object Qgdk_pixbuf, Qglib, Qgobject; static bool init_svg_functions (void) { - HMODULE library, gdklib, glib, gobject; + HMODULE library, gdklib = NULL, glib = NULL, gobject = NULL; if (!(glib = w32_delayed_load (Qglib)) || !(gobject = w32_delayed_load (Qgobject)) || !(gdklib = w32_delayed_load (Qgdk_pixbuf)) || !(library = w32_delayed_load (Qsvg))) - return 0; + { + if (gdklib) FreeLibrary (gdklib); + if (gobject) FreeLibrary (gobject); + if (glib) FreeLibrary (glib); + return 0; + } LOAD_IMGLIB_FN (library, rsvg_handle_new); LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions); @@ -8841,14 +8859,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || !x_defined_color (f, SSDATA (specified_bg), &background, 0)) - { -#ifndef HAVE_NS - background.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &background); -#else - ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1); -#endif - } + x_query_frame_background_color (f, &background); /* SVG pixmaps specify transparency in the last byte, so right shift 8 bits to get rid of it, since emacs doesn't support @@ -9336,6 +9347,8 @@ reset_image_types (void) void syms_of_image (void) { +#include "image.x" + /* Initialize this only once; it will be reset before dumping. */ image_types = NULL; @@ -9410,6 +9423,14 @@ non-numeric, there is no explicit limit on the size of images. */); + GIFLIB_RELEASE) #else make_number (-1) +#endif + ); + DEFSYM (Qlibjpeg_version, "libjpeg-version"); + Fset (Qlibjpeg_version, +#if HAVE_JPEG + make_number (JPEG_LIB_VERSION) +#else + make_number (-1) #endif ); #endif @@ -9461,21 +9482,6 @@ non-numeric, there is no explicit limit on the size of images. */); #endif /* HAVE_NTGUI */ #endif /* HAVE_RSVG */ - defsubr (&Sinit_image_library); -#ifdef HAVE_IMAGEMAGICK - defsubr (&Simagemagick_types); -#endif - defsubr (&Sclear_image_cache); - defsubr (&Simage_flush); - defsubr (&Simage_size); - defsubr (&Simage_mask_p); - defsubr (&Simage_metadata); - -#ifdef GLYPH_DEBUG - defsubr (&Simagep); - defsubr (&Slookup_image); -#endif - DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images, doc: /* Non-nil means always draw a cross over disabled images. Disabled images are those having a `:conversion disabled' property. @@ -9484,7 +9490,7 @@ A cross is always drawn on black & white displays. */); DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path, doc: /* List of directories to search for window system bitmap files. */); - Vx_bitmap_file_path = decode_env_path (0, PATH_BITMAPS); + Vx_bitmap_file_path = decode_env_path (0, PATH_BITMAPS, 0); DEFVAR_LISP ("image-cache-eviction-delay", Vimage_cache_eviction_delay, doc: /* Maximum time after which images are removed from the cache.