X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/adf2fc4a01efe77d73cd52bc9173914ed56ff531..287d70764c83f6054eb2a0ede942eda01c20fcdf:/src/image.c diff --git a/src/image.c b/src/image.c index 1271376bca..38a9227729 100644 --- a/src/image.c +++ b/src/image.c @@ -87,10 +87,12 @@ typedef struct w32_bitmap_record Bitmap_Record; #define x_defined_color w32_defined_color #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits) -/* 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. */ -Lisp_Object Qlibpng_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 @@ -158,16 +160,16 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) /* Functions to access the contents of a bitmap, given an id. */ -int +static int x_bitmap_height (struct frame *f, ptrdiff_t id) { - return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height; + return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].height; } -int +static int x_bitmap_width (struct frame *f, ptrdiff_t id) { - return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width; + return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].width; } #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) @@ -175,7 +177,7 @@ ptrdiff_t x_bitmap_pixmap (struct frame *f, ptrdiff_t id) { /* HAVE_NTGUI needs the explicit cast here. */ - return (ptrdiff_t) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; + return (ptrdiff_t) FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; } #endif @@ -183,7 +185,7 @@ x_bitmap_pixmap (struct frame *f, ptrdiff_t id) int x_bitmap_mask (struct frame *f, ptrdiff_t id) { - return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask; + return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].mask; } #endif @@ -192,7 +194,7 @@ x_bitmap_mask (struct frame *f, ptrdiff_t id) static ptrdiff_t x_allocate_bitmap_record (struct frame *f) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); ptrdiff_t i; if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size) @@ -213,7 +215,7 @@ x_allocate_bitmap_record (struct frame *f) void x_reference_bitmap (struct frame *f, ptrdiff_t id) { - ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; + ++FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; } /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */ @@ -221,7 +223,7 @@ x_reference_bitmap (struct frame *f, ptrdiff_t id) ptrdiff_t x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsigned int height) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); ptrdiff_t id; #ifdef HAVE_X_WINDOWS @@ -235,8 +237,8 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi #ifdef HAVE_NTGUI Pixmap bitmap; bitmap = CreateBitmap (width, height, - FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes, - FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits, + FRAME_DISPLAY_INFO (XFRAME (frame))->n_planes, + FRAME_DISPLAY_INFO (XFRAME (frame))->n_cbits, bits); if (! bitmap) return -1; @@ -280,7 +282,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi ptrdiff_t x_create_bitmap_from_file (struct frame *f, Lisp_Object file) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); #ifdef HAVE_NTGUI return -1; /* W32_TODO : bitmap support */ @@ -379,7 +381,7 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) void x_destroy_bitmap (struct frame *f, ptrdiff_t id) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); if (id > 0) { @@ -454,7 +456,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) unsigned long x, y, xp, xm, yp, ym; GC gc; - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); if (!(id > 0)) return; @@ -1519,7 +1521,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 (); @@ -2455,7 +2457,7 @@ xbm_image_p (Lisp_Object object) } else if (BOOL_VECTOR_P (elt)) { - if (XBOOL_VECTOR (elt)->size < width) + if (bool_vector_size (elt) < width) return 0; } else @@ -2470,7 +2472,7 @@ xbm_image_p (Lisp_Object object) } else if (BOOL_VECTOR_P (data)) { - if (XBOOL_VECTOR (data)->size / height < width) + if (bool_vector_size (data) / height < width) return 0; } else @@ -3024,13 +3026,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 { @@ -3421,7 +3423,7 @@ xpm_image_p (Lisp_Object object) ptrdiff_t x_create_bitmap_from_xpm_data (struct frame *f, const char **bits) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); ptrdiff_t id; int rc; XpmAttributes attrs; @@ -3588,6 +3590,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), @@ -4325,7 +4333,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) two orders of magnitude. Freeing colors on TrueColor visuals is a nop, and pixel colors specify RGB values directly. See also the Xlib spec, chapter 3.1. */ - dpyinfo = FRAME_X_DISPLAY_INFO (f); + dpyinfo = FRAME_DISPLAY_INFO (f); if (dpyinfo->red_bits > 0) { unsigned long pr, pg, pb; @@ -4820,7 +4828,7 @@ x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix, static void x_disable_image (struct frame *f, struct image *img) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); #ifdef HAVE_NTGUI int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits; #else @@ -5104,6 +5112,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. */ @@ -5113,28 +5142,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; @@ -6957,6 +6974,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"); @@ -7203,6 +7223,7 @@ gif_image_p (Lisp_Object object) #ifdef HAVE_GIF #if defined (HAVE_NTGUI) + /* winuser.h might define DrawText to DrawTextA or DrawTextW. Undefine before redefining to avoid a preprocessor warning. */ #ifdef DrawText @@ -7213,20 +7234,38 @@ gif_image_p (Lisp_Object object) #include #undef DrawText +/* Giflib before 5.0 didn't define these macros (used only if HAVE_NTGUI). */ +#ifndef GIFLIB_MINOR +#define GIFLIB_MINOR 0 +#endif +#ifndef GIFLIB_RELEASE +#define GIFLIB_RELEASE 0 +#endif + #else /* HAVE_NTGUI */ #include #endif /* HAVE_NTGUI */ +/* Giflib before 5.0 didn't define these macros. */ +#ifndef GIFLIB_MAJOR +#define GIFLIB_MAJOR 4 +#endif #ifdef WINDOWSNT /* GIF library details. */ DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *)); DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *)); +#if GIFLIB_MAJOR < 5 DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc)); DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *)); +#else +DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc, int *)); +DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *, int *)); +DEF_IMGLIB_FN (char *, GifErrorString, (int)); +#endif static bool init_gif_functions (void) @@ -7240,6 +7279,9 @@ init_gif_functions (void) LOAD_IMGLIB_FN (library, DGifSlurp); LOAD_IMGLIB_FN (library, DGifOpen); LOAD_IMGLIB_FN (library, DGifOpenFileName); +#if GIFLIB_MAJOR >= 5 + LOAD_IMGLIB_FN (library, GifErrorString); +#endif return 1; } @@ -7249,6 +7291,9 @@ init_gif_functions (void) #define fn_DGifSlurp DGifSlurp #define fn_DGifOpen DGifOpen #define fn_DGifOpenFileName DGifOpenFileName +#if 5 <= GIFLIB_MAJOR +# define fn_GifErrorString GifErrorString +#endif #endif /* WINDOWSNT */ @@ -7305,6 +7350,9 @@ 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)) { @@ -7314,14 +7362,27 @@ 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 gif = fn_DGifOpenFileName (SSDATA (file)); if (gif == NULL) { image_error ("Cannot open `%s'", file, Qnil); return 0; } +#else + gif = fn_DGifOpenFileName (SSDATA (file), &gif_err); + if (gif == NULL) + { + image_error ("Cannot open `%s': %s", + file, build_string (fn_GifErrorString (gif_err))); + return 0; + } +#endif } else { @@ -7337,12 +7398,22 @@ gif_load (struct frame *f, struct image *img) memsrc.len = SBYTES (specified_data); memsrc.index = 0; +#if GIFLIB_MAJOR < 5 gif = fn_DGifOpen (&memsrc, gif_read_from_memory); if (!gif) { image_error ("Cannot open memory source `%s'", img->spec, Qnil); return 0; } +#else + gif = fn_DGifOpen (&memsrc, gif_read_from_memory, &gif_err); + if (!gif) + { + image_error ("Cannot open memory source `%s': %s", + img->spec, build_string (fn_GifErrorString (gif_err))); + return 0; + } +#endif } /* Before reading entire contents, check the declared image size. */ @@ -7522,10 +7593,7 @@ gif_load (struct frame *f, struct image *img) y++, row += interlace_increment[pass]) { while (subimg_height <= row) - { - lint_assume (pass < 3); - row = interlace_start[++pass]; - } + row = interlace_start[++pass]; for (x = 0; x < subimg_width; x++) { @@ -8037,7 +8105,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 @@ -8423,6 +8491,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 @@ -8590,7 +8661,9 @@ DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels, (const GdkPixbuf *)); DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha, (const GdkPixbuf *)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample, (const GdkPixbuf *)); +#if ! GLIB_CHECK_VERSION (2, 36, 0) DEF_IMGLIB_FN (void, g_type_init, (void)); +#endif DEF_IMGLIB_FN (void, g_object_unref, (gpointer)); DEF_IMGLIB_FN (void, g_error_free, (GError *)); @@ -8622,7 +8695,9 @@ init_svg_functions (void) LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha); LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample); +#if ! GLIB_CHECK_VERSION (2, 36, 0) LOAD_IMGLIB_FN (gobject, g_type_init); +#endif LOAD_IMGLIB_FN (gobject, g_object_unref); LOAD_IMGLIB_FN (glib, g_error_free); @@ -8647,7 +8722,9 @@ init_svg_functions (void) #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample +#if ! GLIB_CHECK_VERSION (2, 36, 0) #define fn_g_type_init g_type_init +#endif #define fn_g_object_unref g_object_unref #define fn_g_error_free g_error_free #endif /* !WINDOWSNT */ @@ -8732,9 +8809,12 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * int x; int y; - /* g_type_init is a glib function that must be called prior to using - gnome type library functions. */ +#if ! GLIB_CHECK_VERSION (2, 36, 0) + /* g_type_init is a glib function that must be called prior to + using gnome type library functions (obsolete since 2.36.0). */ fn_g_type_init (); +#endif + /* Make a handle to a new rsvg object. */ rsvg_handle = fn_rsvg_handle_new (); @@ -9345,6 +9425,24 @@ non-numeric, there is no explicit limit on the size of images. */); make_number (PNG_LIBPNG_VER) #else make_number (-1) +#endif + ); + DEFSYM (Qlibgif_version, "libgif-version"); + Fset (Qlibgif_version, +#ifdef HAVE_GIF + make_number (GIFLIB_MAJOR * 10000 + + GIFLIB_MINOR * 100 + + 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 @@ -9419,7 +9517,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.