X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/453f40228f8ff3d43665f5bf008b117bf9b9a7dc..991496253a519d728a1041c157b37182a829d156:/src/image.c diff --git a/src/image.c b/src/image.c index 7a6323ad33..86780c62a0 100644 --- a/src/image.c +++ b/src/image.c @@ -30,13 +30,8 @@ along with GNU Emacs. If not, see . */ #endif #include - #include -/* This makes the fields of a Display accessible, in Xlib header files. */ - -#define XLIB_ILLEGAL_ACCESS - #include "lisp.h" #include "frame.h" #include "window.h" @@ -92,10 +87,11 @@ 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 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; #endif /* HAVE_NTGUI */ #ifdef HAVE_NS @@ -145,7 +141,7 @@ static Lisp_Object QCmax_width, QCmax_height; #ifdef HAVE_NS /* Use with images created by ns_image_for_XPM. */ -unsigned long +static unsigned long XGetPixel (XImagePtr ximage, int x, int y) { return ns_get_pixel (ximage, x, y); @@ -153,7 +149,7 @@ XGetPixel (XImagePtr ximage, int x, int y) /* Use with images created by ns_image_for_XPM; alpha set to 1; pixel is assumed to be in RGB form. */ -void +static void XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) { ns_put_pixel (ximage, x, y, pixel); @@ -166,13 +162,13 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) 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 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) @@ -180,7 +176,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 @@ -188,7 +184,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 @@ -197,7 +193,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) @@ -218,7 +214,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. */ @@ -226,7 +222,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 @@ -240,8 +236,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; @@ -285,7 +281,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 */ @@ -384,7 +380,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) { @@ -459,7 +455,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; @@ -563,7 +559,6 @@ static void x_emboss (struct frame *, struct image *); static void x_build_heuristic_mask (struct frame *, struct image *, Lisp_Object); #ifdef WINDOWSNT -extern Lisp_Object Vlibrary_cache; #define CACHE_IMAGE_TYPE(type, status) \ do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0) #else @@ -1042,7 +1037,7 @@ void prepare_image_for_display (struct frame *f, struct image *img) { /* We're about to display IMG, so set its timestamp to `now'. */ - img->timestamp = current_emacs_time (); + img->timestamp = current_timespec (); /* If IMG doesn't have a pixmap yet, load it now, using the image type dependent loader function. */ @@ -1481,7 +1476,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) else if (INTEGERP (Vimage_cache_eviction_delay)) { /* Free cache based on timestamp. */ - EMACS_TIME old, t; + struct timespec old, t; double delay; ptrdiff_t nimages = 0; @@ -1496,13 +1491,13 @@ clear_image_cache (struct frame *f, Lisp_Object filter) delay = 1600 * delay / nimages / nimages; delay = max (delay, 1); - t = current_emacs_time (); - old = sub_emacs_time (t, EMACS_TIME_FROM_DOUBLE (delay)); + t = current_timespec (); + old = timespec_sub (t, dtotimespec (delay)); for (i = 0; i < c->used; ++i) { struct image *img = c->images[i]; - if (img && EMACS_TIME_LT (img->timestamp, old)) + if (img && timespec_cmp (img->timestamp, old) < 0) { free_image (f, img); ++nfreed; @@ -1765,7 +1760,7 @@ lookup_image (struct frame *f, Lisp_Object spec) } /* We're using IMG, so set its timestamp to `now'. */ - img->timestamp = current_emacs_time (); + img->timestamp = current_timespec (); /* Value is the image id. */ return img->id; @@ -2713,10 +2708,13 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e LA1 = xbm_scan (&s, end, buffer, &value) #define expect(TOKEN) \ - if (LA1 != (TOKEN)) \ - goto failure; \ - else \ - match () + do \ + { \ + if (LA1 != (TOKEN)) \ + goto failure; \ + match (); \ + } \ + while (0) #define expect_ident(IDENT) \ if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \ @@ -3424,7 +3422,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; @@ -3976,10 +3974,13 @@ xpm_load_image (struct frame *f, LA1 = xpm_scan (&s, end, &beg, &len) #define expect(TOKEN) \ - if (LA1 != (TOKEN)) \ - goto failure; \ - else \ - match () + do \ + { \ + if (LA1 != (TOKEN)) \ + goto failure; \ + match (); \ + } \ + while (0) #define expect_ident(IDENT) \ if (LA1 == XPM_TK_IDENT \ @@ -4325,7 +4326,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 +4821,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 @@ -4932,7 +4933,7 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how) int row_width; #endif /* HAVE_NTGUI */ int x, y; - bool rc, use_img_background; + bool use_img_background; unsigned long bg = 0; if (img->mask) @@ -4941,9 +4942,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how) #ifndef HAVE_NTGUI #ifndef HAVE_NS /* Create an image and pixmap serving as mask. */ - rc = image_create_x_image_and_pixmap (f, img, img->width, img->height, 1, - &mask_img, 1); - if (!rc) + if (! image_create_x_image_and_pixmap (f, img, img->width, img->height, 1, + &mask_img, 1)) return; #endif /* !HAVE_NS */ #else @@ -7203,7 +7203,21 @@ gif_image_p (Lisp_Object object) #ifdef HAVE_GIF +/* Giflib before 5.0 didn't define these macros. */ +#ifndef GIFLIB_MAJOR +#define GIFLIB_MAJOR 4 +#endif + #if defined (HAVE_NTGUI) + +/* 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 + /* winuser.h might define DrawText to DrawTextA or DrawTextW. Undefine before redefining to avoid a preprocessor warning. */ #ifdef DrawText @@ -7220,14 +7234,19 @@ gif_image_p (Lisp_Object object) #endif /* HAVE_NTGUI */ - #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) @@ -7241,6 +7260,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; } @@ -7250,6 +7272,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 */ @@ -7306,6 +7331,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)) { @@ -7317,12 +7345,22 @@ gif_load (struct frame *f, struct image *img) } /* 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 { @@ -7338,12 +7376,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. */ @@ -7524,7 +7572,7 @@ gif_load (struct frame *f, struct image *img) { while (subimg_height <= row) { - lint_assume (pass < 3); + assume (pass < 3); row = interlace_start[++pass]; } @@ -7878,11 +7926,11 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent]) struct animation_cache { - char *signature; MagickWand *wand; int index; - EMACS_TIME update_time; + struct timespec update_time; struct animation_cache *next; + char signature[FLEXIBLE_ARRAY_MEMBER]; }; static struct animation_cache *animation_cache = NULL; @@ -7890,12 +7938,13 @@ static struct animation_cache *animation_cache = NULL; static struct animation_cache * imagemagick_create_cache (char *signature) { - struct animation_cache *cache = xmalloc (sizeof *cache); - cache->signature = signature; + struct animation_cache *cache + = xmalloc (offsetof (struct animation_cache, signature) + + strlen (signature) + 1); cache->wand = 0; cache->index = 0; cache->next = 0; - cache->update_time = current_emacs_time (); + strcpy (cache->signature, signature); return cache; } @@ -7904,17 +7953,16 @@ static void imagemagick_prune_animation_cache (void) { struct animation_cache **pcache = &animation_cache; - EMACS_TIME old = sub_emacs_time (current_emacs_time (), - make_emacs_time (60, 0)); + struct timespec old = timespec_sub (current_timespec (), + make_timespec (60, 0)); while (*pcache) { struct animation_cache *cache = *pcache; - if (EMACS_TIME_LE (old, cache->update_time)) + if (timespec_cmp (old, cache->update_time) <= 0) pcache = &cache->next; else { - DestroyString (cache->signature); if (cache->wand) DestroyMagickWand (cache->wand); *pcache = cache->next; @@ -7928,28 +7976,25 @@ imagemagick_get_animation_cache (MagickWand *wand) { char *signature = MagickGetImageSignature (wand); struct animation_cache *cache; + struct animation_cache **pcache = &animation_cache; imagemagick_prune_animation_cache (); - cache = animation_cache; - if (! cache) + while (1) { - animation_cache = imagemagick_create_cache (signature); - return animation_cache; - } - - while (strcmp (signature, cache->signature) && - cache->next) - cache = cache->next; - - if (strcmp (signature, cache->signature)) - { - cache->next = imagemagick_create_cache (signature); - return cache->next; + cache = *pcache; + if (! cache) + { + *pcache = cache = imagemagick_create_cache (signature); + break; + } + if (strcmp (signature, cache->signature) == 0) + break; + pcache = &cache->next; } DestroyString (signature); - cache->update_time = current_emacs_time (); + cache->update_time = current_timespec (); return cache; } @@ -8594,7 +8639,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 *)); @@ -8626,7 +8673,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); @@ -8651,7 +8700,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 */ @@ -8736,9 +8787,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 (); @@ -9349,6 +9403,16 @@ 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 ); #endif