X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a9a61c77b3effd0e00b20ff714e430ee6b2a937a..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/image.c diff --git a/src/image.c b/src/image.c index e53ad0b4a3..7fa28840c1 100644 --- a/src/image.c +++ b/src/image.c @@ -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 @@ -160,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) { @@ -171,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 @@ -998,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); @@ -1231,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 ***********************************************************************/ @@ -1801,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 @@ -1930,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); @@ -2019,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; } @@ -2272,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 @@ -2291,7 +2282,7 @@ slurp_file (char *file, ptrdiff_t *size) } } - unbind_to (count, Qnil); + dynwind_end (); } return buf; @@ -2797,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) { @@ -3696,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) { @@ -3952,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; @@ -4493,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) @@ -5505,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. */ @@ -5883,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); - - 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 */ + 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; - fn_png_set_background (png_ptr, &frame_background, + fn_png_set_background (png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } @@ -5942,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; @@ -6061,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) { @@ -6071,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 */ @@ -6261,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 }; @@ -6468,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. */ @@ -6478,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; @@ -6511,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); @@ -6551,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); @@ -7055,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); @@ -7261,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)); @@ -7331,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. */ @@ -7355,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)) { @@ -7425,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; } @@ -7434,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; } @@ -7446,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; } } @@ -7464,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; } @@ -7482,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; } } @@ -7490,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; } @@ -7661,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))) @@ -8235,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); @@ -8394,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, @@ -8434,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); @@ -8537,7 +8519,6 @@ and `imagemagick-types-inhibit'. */) ExceptionInfo ex; char **imtypes; size_t i; - Lisp_Object Qimagemagicktype; GetExceptionInfo(&ex); imtypes = GetMagickList ("*", &numf, &ex); @@ -8545,8 +8526,8 @@ 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]); } @@ -8658,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 *)); @@ -8680,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); @@ -8874,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 @@ -9369,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; @@ -9502,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.