/* Functions for image support on window system.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <unistd.h>
#endif
+#ifdef HAVE_PNG
+#if defined HAVE_LIBPNG_PNG_H
+# include <libpng/png.h>
+#else
+# include <png.h>
+#endif
+#endif
+
+#include <setjmp.h>
+
/* This makes the fields of a Display accessible, in Xlib header files. */
#define XLIB_ILLEGAL_ACCESS
#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);
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
the bitmaps yourself. That is, creating a bitmap from the same
data more than once will not be caught. */
-#ifdef MAC_OS
-
-static XImagePtr
-XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
- Display *display; /* not used */
- Pixmap pixmap;
- int x, y; /* not used */
- unsigned int width, height; /* not used */
- unsigned long plane_mask; /* not used */
- int format; /* not used */
-{
-#if !USE_MAC_IMAGE_IO
-#if GLYPH_DEBUG
- xassert (x == 0 && y == 0);
- {
- Rect ri, rp;
- SetRect (&ri, 0, 0, width, height);
- xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
- }
- xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
-#endif
-
- LockPixels (GetGWorldPixMap (pixmap));
-#endif
-
- return pixmap;
-}
-
-static void
-XPutPixel (ximage, x, y, pixel)
- XImagePtr ximage;
- int x, y;
- unsigned long pixel;
-{
-#if USE_MAC_IMAGE_IO
- if (ximage->bits_per_pixel == 32)
- ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
- else
- ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
-#else
- PixMapHandle pixmap = GetGWorldPixMap (ximage);
- short depth = GetPixDepth (pixmap);
-
-#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
- if (depth == 32)
- {
- char *base_addr = GetPixBaseAddr (pixmap);
- short row_bytes = GetPixRowBytes (pixmap);
-
- ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
- }
- else
-#endif
- if (depth == 1)
- {
- char *base_addr = GetPixBaseAddr (pixmap);
- short row_bytes = GetPixRowBytes (pixmap);
-
- if (pixel == PIX_MASK_DRAW)
- base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
- else
- base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
- }
- else
- {
- CGrafPtr old_port;
- GDHandle old_gdh;
- RGBColor color;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (ximage, NULL);
-
- color.red = RED16_FROM_ULONG (pixel);
- color.green = GREEN16_FROM_ULONG (pixel);
- color.blue = BLUE16_FROM_ULONG (pixel);
-
- SetCPixel (x, y, &color);
-
- SetGWorld (old_port, old_gdh);
- }
-#endif
-}
-
-static unsigned long
-XGetPixel (ximage, x, y)
- XImagePtr ximage;
- int x, y;
-{
-#if USE_MAC_IMAGE_IO
- if (ximage->bits_per_pixel == 32)
- return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
- else
- return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
-#else
- PixMapHandle pixmap = GetGWorldPixMap (ximage);
- short depth = GetPixDepth (pixmap);
-
-#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
- if (depth == 32)
- {
- char *base_addr = GetPixBaseAddr (pixmap);
- short row_bytes = GetPixRowBytes (pixmap);
-
- return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
- }
- else
-#endif
- if (depth == 1)
- {
- char *base_addr = GetPixBaseAddr (pixmap);
- short row_bytes = GetPixRowBytes (pixmap);
-
- if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
- return PIX_MASK_DRAW;
- else
- return PIX_MASK_RETAIN;
- }
- else
- {
- CGrafPtr old_port;
- GDHandle old_gdh;
- RGBColor color;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (ximage, NULL);
-
- GetCPixel (x, y, &color);
-
- SetGWorld (old_port, old_gdh);
- return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
- }
-#endif
-}
-
-static void
-XDestroyImage (ximg)
- XImagePtr ximg;
-{
-#if !USE_MAC_IMAGE_IO
- UnlockPixels (GetGWorldPixMap (ximg));
-#endif
-}
-
-#if USE_CG_DRAWING
-#if USE_MAC_IMAGE_IO
-void
-mac_data_provider_release_data (info, data, size)
- void *info;
- const void *data;
- size_t size;
-{
- xfree ((void *)data);
-}
-#endif
-
-static CGImageRef
-mac_create_cg_image_from_image (f, img)
- struct frame *f;
- struct image *img;
-{
-#if USE_MAC_IMAGE_IO
- XImagePtr ximg = img->pixmap;
- CGDataProviderRef provider;
- CGImageRef result;
-
- if (img->mask)
- {
- int x, y;
- unsigned long color, alpha;
-
- for (y = 0; y < ximg->height; y++)
- for (x = 0; x < ximg->width; x++)
- {
- color = XGetPixel (ximg, x, y);
- alpha = XGetPixel (img->mask, x, y);
- XPutPixel (ximg, x, y,
- ARGB_TO_ULONG (alpha,
- RED_FROM_ULONG (color)
- * alpha / PIX_MASK_DRAW,
- GREEN_FROM_ULONG (color)
- * alpha / PIX_MASK_DRAW,
- BLUE_FROM_ULONG (color)
- * alpha / PIX_MASK_DRAW));
- }
- xfree (img->mask->data);
- img->mask->data = NULL;
- }
- BLOCK_INPUT;
- provider = CGDataProviderCreateWithData (NULL, ximg->data,
- ximg->bytes_per_line * ximg->height,
- mac_data_provider_release_data);
- ximg->data = NULL;
- result = CGImageCreate (ximg->width, ximg->height, 8, 32,
- ximg->bytes_per_line, mac_cg_color_space_rgb,
- ((img->mask ? kCGImageAlphaPremultipliedFirst
- : kCGImageAlphaNoneSkipFirst)
- | kCGBitmapByteOrder32Host),
- provider, NULL, 0, kCGRenderingIntentDefault);
- CGDataProviderRelease (provider);
- UNBLOCK_INPUT;
-
- return result;
-#else
- Pixmap mask;
- CGImageRef result = NULL;
-
- BLOCK_INPUT;
- if (img->mask)
- mask = img->mask;
- else
- {
- mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- img->width, img->height, 1);
- if (mask)
- {
- CGrafPtr old_port;
- GDHandle old_gdh;
- Rect r;
-
- GetGWorld (&old_port, &old_gdh);
- SetGWorld (mask, NULL);
- BackColor (blackColor); /* Don't mask. */
- SetRect (&r, 0, 0, img->width, img->height);
- EraseRect (&r);
- SetGWorld (old_port, old_gdh);
- }
- }
- if (mask)
- {
- CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
- GetGWorldPixMap (mask), &result);
- if (mask != img->mask)
- XFreePixmap (FRAME_X_DISPLAY (f), mask);
- }
- UNBLOCK_INPUT;
-
- return result;
-#endif
-}
-#endif /* USE_CG_DRAWING */
-#endif /* MAC_OS */
-
#ifdef HAVE_NS
XImagePtr
XGetImage (Display *display, Pixmap pixmap, int x, int y,
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
extern Lisp_Object QCdata, QCtype;
extern Lisp_Object Qcenter;
-Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
+Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data;
Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
case IMAGE_FUNCTION_VALUE:
value = indirect_function (value);
if (SUBRP (value)
- || COMPILEDP (value)
+ || FUNVECP (value)
|| (CONSP (value) && EQ (XCAR (value), Qlambda)))
break;
return 0;
return mask;
}
-DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
- doc: /* Return extension data for image SPEC.
+DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0,
+ doc: /* Return metadata for image SPEC.
FRAME is the frame on which the image will be displayed. FRAME nil
or omitted means use the selected frame. */)
(spec, frame)
{
Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
img->pixmap = NO_PIXMAP;
-#ifdef HAVE_NS
- if (img->background_valid)
- ns_free_indexed_color(img->background);
-#endif
+ /* NOTE (HAVE_NS): background color is NOT an indexed color! */
img->background_valid = 0;
}
{
struct image_cache *c = FRAME_IMAGE_CACHE (f);
- if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
+ if (c)
{
- EMACS_TIME t;
- unsigned long old;
- int i, nfreed;
-
- EMACS_GET_TIME (t);
- old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
+ int i, nfreed = 0;
/* Block input so that we won't be interrupted by a SIGIO
while being in an inconsistent state. */
BLOCK_INPUT;
- for (i = nfreed = 0; i < c->used; ++i)
+ if (!NILP (filter))
+ {
+ /* Filter image cache. */
+ for (i = 0; i < c->used; ++i)
+ {
+ struct image *img = c->images[i];
+ if (img && (EQ (Qt, filter)
+ || !NILP (Fmember (filter, img->dependencies))))
+ {
+ free_image (f, img);
+ ++nfreed;
+ }
+ }
+ }
+ else if (INTEGERP (Vimage_cache_eviction_delay))
{
- struct image *img = c->images[i];
- if (img != NULL
- && (NILP (filter) ? img->timestamp < old
- : (EQ (Qt, filter)
- || !NILP (Fmember (filter, img->dependencies)))))
+ /* Free cache based on timestamp. */
+ EMACS_TIME t;
+ unsigned long old;
+ int delay, nimages = 0;
+
+ for (i = 0; i < c->used; ++i)
+ if (c->images[i])
+ nimages++;
+
+ /* If the number of cached images has grown unusually large,
+ decrease the cache eviction delay (Bug#6230). */
+ delay = XFASTINT (Vimage_cache_eviction_delay);
+ if (nimages > 40)
+ delay = max (1, 1600 * delay / (nimages*nimages));
+
+ EMACS_GET_TIME (t);
+ old = EMACS_SECS (t) - delay;
+
+ for (i = 0; i < c->used; ++i)
{
- free_image (f, img);
- ++nfreed;
+ struct image *img = c->images[i];
+ if (img && img->timestamp < old)
+ {
+ free_image (f, img);
+ ++nfreed;
+ }
}
}
}
-DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
+DEFUN ("image-flush", Fimage_flush, Simage_flush,
1, 2, 0,
- doc: /* Refresh the image with specification SPEC on frame FRAME.
-If SPEC specifies an image file, the displayed image is updated with
-the current contents of that file.
+ doc: /* Fush the image with specification SPEC on frame FRAME.
+This removes the image from the Emacs image cache. If SPEC specifies
+an image file, the next redisplay of this image will read from the
+current contents of that file.
+
FRAME nil or omitted means use the selected frame.
FRAME t means refresh the image on all frames. */)
(spec, frame)
static int xbm_image_p P_ ((Lisp_Object object));
static int xbm_read_bitmap_data P_ ((struct frame *f,
unsigned char *, unsigned char *,
- int *, int *, unsigned char **));
+ int *, int *, unsigned char **, int));
static int xbm_file_p P_ ((Lisp_Object));
/* Vector of image_keyword structures describing the format
of valid XBM image specifications. */
-static struct image_keyword xbm_format[XBM_LAST] =
+static const struct image_keyword xbm_format[XBM_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":file", IMAGE_STRING_VALUE, 0},
buffer's end. Set *WIDTH and *HEIGHT to the width and height of
the image. Return in *DATA the bitmap data allocated with xmalloc.
Value is non-zero if successful. DATA null means just test if
- CONTENTS looks like an in-memory XBM file. */
+ CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR
+ is non-zero, inhibit the call to image_error when the image size is
+ invalid (the bitmap remains unread). */
static int
-xbm_read_bitmap_data (f, contents, end, width, height, data)
+xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error)
struct frame *f;
unsigned char *contents, *end;
int *width, *height;
unsigned char **data;
+ int inhibit_image_error;
{
unsigned char *s = contents;
char buffer[BUFSIZ];
}
if (!check_image_size (f, *width, *height))
- goto failure;
+ {
+ if (!inhibit_image_error)
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ goto failure;
+ }
else if (data == NULL)
goto success;
unsigned char *data;
int success_p = 0;
- rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
+ rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
+ &data, 0);
if (rc)
{
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
int w, h;
return (STRINGP (data)
&& xbm_read_bitmap_data (NULL, SDATA (data),
- (SDATA (data)
- + SBYTES (data)),
- &w, &h, NULL));
+ (SDATA (data) + SBYTES (data)),
+ &w, &h, NULL, 1));
}
int nbytes, i;
/* Windows mono bitmaps are reversed compared with X. */
invertedBits = bits;
- nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
+ nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
* img->height;
bits = (char *) alloca(nbytes);
for (i = 0; i < nbytes; i++)
/* Vector of image_keyword structures describing the format
of valid XPM image specifications. */
-static struct image_keyword xpm_format[XPM_LAST] =
+static const struct image_keyword xpm_format[XPM_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":file", IMAGE_STRING_VALUE, 0},
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
goto failure;
}
{
XColor *row = p;
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
for (x = 0; x < img->width; ++x, ++p)
- p->pixel = XGetPixel (ximg, x, y);
+ p->pixel = GET_PIXEL (ximg, x, y);
if (rgb_p)
x_query_colors (f, row, img->width);
p->pixel = GET_PIXEL (ximg, x, y);
if (rgb_p)
{
-#if defined (HAVE_NS)
p->red = RED16_FROM_ULONG (p->pixel);
p->green = GREEN16_FROM_ULONG (p->pixel);
p->blue = BLUE16_FROM_ULONG (p->pixel);
-#endif /* HAVE_NS */
-#ifdef HAVE_NTGUI
- p->red = 256 * GetRValue (p->pixel);
- p->green = 256 * GetGValue (p->pixel);
- p->blue = 256 * GetBValue (p->pixel);
-#endif /* HAVE_NTGUI */
}
}
#endif /* HAVE_X_WINDOWS */
Display *dpy = FRAME_X_DISPLAY (f);
GC gc;
-#ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
+#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword pbm_format[PBM_LAST] =
+static const struct image_keyword pbm_format[PBM_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":file", IMAGE_STRING_VALUE, 0},
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
goto error;
}
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword png_format[PNG_LAST] =
+static const struct image_keyword png_format[PNG_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
#ifdef HAVE_PNG
-#if defined HAVE_LIBPNG_PNG_H
-# include <libpng/png.h>
-#else
-# include <png.h>
-#endif
-
#ifdef HAVE_NTGUI
/* PNG library details. */
DEF_IMGLIB_FN (png_get_io_ptr);
-DEF_IMGLIB_FN (png_check_sig);
+DEF_IMGLIB_FN (png_sig_cmp);
DEF_IMGLIB_FN (png_create_read_struct);
DEF_IMGLIB_FN (png_create_info_struct);
DEF_IMGLIB_FN (png_destroy_read_struct);
return 0;
LOAD_IMGLIB_FN (library, png_get_io_ptr);
- LOAD_IMGLIB_FN (library, png_check_sig);
+ LOAD_IMGLIB_FN (library, png_sig_cmp);
LOAD_IMGLIB_FN (library, png_create_read_struct);
LOAD_IMGLIB_FN (library, png_create_info_struct);
LOAD_IMGLIB_FN (library, png_destroy_read_struct);
#else
#define fn_png_get_io_ptr png_get_io_ptr
-#define fn_png_check_sig png_check_sig
+#define fn_png_sig_cmp png_sig_cmp
#define fn_png_create_read_struct png_create_read_struct
#define fn_png_create_info_struct png_create_info_struct
#define fn_png_destroy_read_struct png_destroy_read_struct
/* Check PNG signature. */
if (fread (sig, 1, sizeof sig, fp) != sizeof sig
- || !fn_png_check_sig (sig, sizeof sig))
+ || fn_png_sig_cmp (sig, 0, sizeof sig))
{
image_error ("Not a PNG file: `%s'", file, Qnil);
UNGCPRO;
/* Check PNG signature. */
if (tbr.len < sizeof sig
- || !fn_png_check_sig (tbr.bytes, sizeof sig))
+ || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
{
image_error ("Not a PNG image: `%s'", img->spec, Qnil);
UNGCPRO;
&interlace_type, NULL, NULL);
if (!check_image_size (f, width, height))
- goto error;
-
+ {
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ goto error;
+ }
/* If image contains simply transparency data, we prefer to
construct a clipping mask. */
if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
if (STRINGP (specified_bg))
/* The user specified `:background', use that. */
{
- /* W32 version incorrectly used COLORREF here!! ++kfs */
XColor color;
if (x_defined_color (f, SDATA (specified_bg), &color, 0))
{
{
/* We use the current frame background, ignoring any default
background color set by the image. */
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
XColor color;
png_color_16 frame_background;
frame_background.blue = color.blue >> shift;
#endif /* HAVE_X_WINDOWS */
-#ifdef HAVE_NTGUI
- COLORREF color;
- png_color_16 frame_background;
- color = FRAME_BACKGROUND_PIXEL (f);
-#if 0 /* W32 TODO : Colormap support. */
- x_query_color (f, &color);
-#endif
- bzero (&frame_background, sizeof frame_background);
- frame_background.red = GetRValue (color);
- frame_background.green = GetGValue (color);
- frame_background.blue = GetBValue (color);
-#endif /* HAVE_NTGUI */
-
fn_png_set_background (png_ptr, &frame_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
}
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword jpeg_format[JPEG_LAST] =
+static const struct image_keyword jpeg_format[JPEG_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
#include <jpeglib.h>
#include <jerror.h>
-#include <setjmp.h>
#ifdef HAVE_STLIB_H_1
#define HAVE_STDLIB_H 1
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
longjmp (mgr.setjmp_buffer, 2);
}
TIFF_HEURISTIC_MASK,
TIFF_MASK,
TIFF_BACKGROUND,
+ TIFF_INDEX,
TIFF_LAST
};
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword tiff_format[TIFF_LAST] =
+static const struct image_keyword tiff_format[TIFF_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
};
/* Structure describing the image type `tiff'. */
DEF_IMGLIB_FN (TIFFGetField);
DEF_IMGLIB_FN (TIFFReadRGBAImage);
DEF_IMGLIB_FN (TIFFClose);
+DEF_IMGLIB_FN (TIFFSetDirectory);
static int
init_tiff_functions (Lisp_Object libraries)
LOAD_IMGLIB_FN (library, TIFFGetField);
LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
LOAD_IMGLIB_FN (library, TIFFClose);
+ LOAD_IMGLIB_FN (library, TIFFSetDirectory);
return 1;
}
#define fn_TIFFGetField TIFFGetField
#define fn_TIFFReadRGBAImage TIFFReadRGBAImage
#define fn_TIFFClose TIFFClose
-
+#define fn_TIFFSetDirectory TIFFSetDirectory
#endif /* HAVE_NTGUI */
Lisp_Object file, specified_file;
Lisp_Object specified_data;
TIFF *tiff;
- int width, height, x, y;
+ int width, height, x, y, count;
uint32 *buf;
- int rc;
+ int rc, rc2;
XImagePtr ximg;
struct gcpro gcpro1;
tiff_memory_source memsrc;
+ Lisp_Object image;
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
}
}
+ image = image_spec_value (img->spec, QCindex, NULL);
+ if (INTEGERP (image))
+ {
+ int ino = XFASTINT (image);
+ if (!fn_TIFFSetDirectory (tiff, ino))
+ {
+ image_error ("Invalid image number `%s' in image `%s'",
+ image, img->spec);
+ fn_TIFFClose (tiff);
+ UNGCPRO;
+ return 0;
+ }
+ }
+
/* Get width and height of the image, and allocate a raster buffer
of width x height 32-bit values. */
fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ fn_TIFFClose (tiff);
UNGCPRO;
return 0;
}
buf = (uint32 *) xmalloc (width * height * sizeof *buf);
rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+
+ /* Count the number of images in the file. */
+ for (count = 1, rc2 = 1; rc2; count++)
+ rc2 = fn_TIFFSetDirectory (tiff, count);
+
+ if (count > 1)
+ img->data.lisp_val = Fcons (Qcount,
+ Fcons (make_number (count),
+ img->data.lisp_val));
+
fn_TIFFClose (tiff);
if (!rc)
{
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword gif_format[GIF_LAST] =
+static const struct image_keyword gif_format[GIF_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
struct frame *f;
struct image *img;
{
- /* IMG->data.ptr_val may contain extension data. */
+ /* IMG->data.ptr_val may contain metadata with extension data. */
img->data.lisp_val = Qnil;
x_clear_image (f, img);
}
/* Load GIF image IMG for use on frame F. Value is non-zero if
successful. */
-static int interlace_start[] = {0, 4, 2, 1};
-static int interlace_increment[] = {8, 8, 4, 2};
+static const int interlace_start[] = {0, 4, 2, 1};
+static const int interlace_increment[] = {8, 8, 4, 2};
static int
gif_load (f, img)
/* Before reading entire contents, check the declared image size. */
if (!check_image_size (f, gif->SWidth, gif->SHeight))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
fn_DGifCloseFile (gif);
UNGCPRO;
return 0;
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
fn_DGifCloseFile (gif);
UNGCPRO;
return 0;
}
}
- /* Save GIF image extension data for `image-extension-data'.
- Format is (count IMAGES FUNCTION "BYTES" ...). */
+ /* Save GIF image extension data for `image-metadata'.
+ Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)). */
img->data.lisp_val = Qnil;
if (gif->SavedImages[ino].ExtensionBlockCount > 0)
{
img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
Fcons (make_number (ext->Function),
img->data.lisp_val));
- img->data.lisp_val = Fnreverse (img->data.lisp_val);
+ img->data.lisp_val = Fcons (Qextension_data,
+ Fcons (Fnreverse (img->data.lisp_val),
+ Qnil));
}
if (gif->ImageCount > 1)
img->data.lisp_val = Fcons (Qcount,
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword svg_format[SVG_LAST] =
+static const struct image_keyword svg_format[SVG_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
DEF_IMGLIB_FN (g_object_unref);
DEF_IMGLIB_FN (g_error_free);
-Lisp_Object Qgdk_pixbuf, Qglib;
+Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
static int
init_svg_functions (Lisp_Object libraries)
{
- HMODULE library, gdklib, glib;
+ 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)))
return 0;
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
- LOAD_IMGLIB_FN (glib, g_type_init);
- LOAD_IMGLIB_FN (glib, g_object_unref);
+ LOAD_IMGLIB_FN (gobject, g_type_init);
+ LOAD_IMGLIB_FN (gobject, g_object_unref);
LOAD_IMGLIB_FN (glib, g_error_free);
+
return 1;
}
gnome type library functions. */
fn_g_type_init ();
/* Make a handle to a new rsvg object. */
- rsvg_handle = fn_rsvg_handle_new ();
+ rsvg_handle = (RsvgHandle *) fn_rsvg_handle_new ();
/* Parse the contents argument and fill in the rsvg_handle. */
fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
if (! check_image_size (f, dimension_data.width, dimension_data.height))
- goto rsvg_error;
+ {
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ goto rsvg_error;
+ }
/* We can now get a valid pixel buffer from the svg file, if all
went ok. */
- pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
+ pixbuf = (GdkPixbuf *) fn_rsvg_handle_get_pixbuf (rsvg_handle);
if (!pixbuf) goto rsvg_error;
fn_g_object_unref (rsvg_handle);
/* Extract some meta data from the svg handle. */
width = fn_gdk_pixbuf_get_width (pixbuf);
height = fn_gdk_pixbuf_get_height (pixbuf);
- pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
+ pixels = (const guint8 *) fn_gdk_pixbuf_get_pixels (pixbuf);
rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
/* Validate the svg meta data. */
/* Handle alpha channel by combining the image with a background
color. */
specified_bg = image_spec_value (img->spec, QCbackground, NULL);
- if (STRINGP (specified_bg)
- && x_defined_color (f, SDATA (specified_bg), &background, 0))
+ if (!STRINGP (specified_bg)
+ || !x_defined_color (f, SDATA (specified_bg), &background, 0))
{
- background.red >>= 8;
- background.green >>= 8;
- background.blue >>= 8;
- }
- else
- {
-#ifdef HAVE_X_WINDOWS
- background.pixel = FRAME_BACKGROUND_PIXEL (f);
- x_query_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
- transparency. */
- background.red >>= 8;
- background.green >>= 8;
- background.blue >>= 8;
-#elif defined (HAVE_NTGUI)
+#ifndef HAVE_NS
background.pixel = FRAME_BACKGROUND_PIXEL (f);
-#if 0 /* W32 TODO : Colormap support. */
x_query_color (f, &background);
-#endif
-
- /* SVG pixmaps specify transparency in the last byte, so right
- shift 8 bits to get rid of it, since emacs doesn't support
- transparency. */
- background.red >>= 8;
- background.green >>= 8;
- background.blue >>= 8;
-#else /* not HAVE_X_WINDOWS*/
-#error FIXME
+#else
+ ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1);
#endif
}
+ /* SVG pixmaps specify transparency in the last byte, so right
+ shift 8 bits to get rid of it, since emacs doesn't support
+ transparency. */
+ background.red >>= 8;
+ background.green >>= 8;
+ background.blue >>= 8;
+
/* This loop handles opacity values, since Emacs assumes
non-transparent images. Each pixel must be "flattened" by
calculating the resulting color, given the transparency of the
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
-static struct image_keyword gs_format[GS_LAST] =
+static const struct image_keyword gs_format[GS_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
{":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
if (!check_image_size (f, img->width, img->height))
{
- image_error ("Invalid image size", Qnil, Qnil);
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
return 0;
}
support the image type. Types 'pbm and 'xbm don't need to be
listed; they are always supported. */);
Vimage_library_alist = Qnil;
- Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
+ Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
DEFVAR_LISP ("max-image-size", &Vmax_image_size,
doc: /* Maximum size of images.
Vimage_type_cache = Qnil;
staticpro (&Vimage_type_cache);
- Qpbm = intern ("pbm");
+ Qpbm = intern_c_string ("pbm");
staticpro (&Qpbm);
ADD_IMAGE_TYPE (Qpbm);
- Qxbm = intern ("xbm");
+ Qxbm = intern_c_string ("xbm");
staticpro (&Qxbm);
ADD_IMAGE_TYPE (Qxbm);
define_image_type (&xbm_type, 1);
define_image_type (&pbm_type, 1);
- Qcount = intern ("count");
+ Qcount = intern_c_string ("count");
staticpro (&Qcount);
+ Qextension_data = intern_c_string ("extension-data");
+ staticpro (&Qextension_data);
- QCascent = intern (":ascent");
+ QCascent = intern_c_string (":ascent");
staticpro (&QCascent);
- QCmargin = intern (":margin");
+ QCmargin = intern_c_string (":margin");
staticpro (&QCmargin);
- QCrelief = intern (":relief");
+ QCrelief = intern_c_string (":relief");
staticpro (&QCrelief);
- QCconversion = intern (":conversion");
+ QCconversion = intern_c_string (":conversion");
staticpro (&QCconversion);
- QCcolor_symbols = intern (":color-symbols");
+ QCcolor_symbols = intern_c_string (":color-symbols");
staticpro (&QCcolor_symbols);
- QCheuristic_mask = intern (":heuristic-mask");
+ QCheuristic_mask = intern_c_string (":heuristic-mask");
staticpro (&QCheuristic_mask);
- QCindex = intern (":index");
+ QCindex = intern_c_string (":index");
staticpro (&QCindex);
- QCmatrix = intern (":matrix");
+ QCmatrix = intern_c_string (":matrix");
staticpro (&QCmatrix);
- QCcolor_adjustment = intern (":color-adjustment");
+ QCcolor_adjustment = intern_c_string (":color-adjustment");
staticpro (&QCcolor_adjustment);
- QCmask = intern (":mask");
+ QCmask = intern_c_string (":mask");
staticpro (&QCmask);
- Qlaplace = intern ("laplace");
+ Qlaplace = intern_c_string ("laplace");
staticpro (&Qlaplace);
- Qemboss = intern ("emboss");
+ Qemboss = intern_c_string ("emboss");
staticpro (&Qemboss);
- Qedge_detection = intern ("edge-detection");
+ Qedge_detection = intern_c_string ("edge-detection");
staticpro (&Qedge_detection);
- Qheuristic = intern ("heuristic");
+ Qheuristic = intern_c_string ("heuristic");
staticpro (&Qheuristic);
- Qpostscript = intern ("postscript");
+ Qpostscript = intern_c_string ("postscript");
staticpro (&Qpostscript);
#ifdef HAVE_GHOSTSCRIPT
ADD_IMAGE_TYPE (Qpostscript);
- QCloader = intern (":loader");
+ QCloader = intern_c_string (":loader");
staticpro (&QCloader);
- QCbounding_box = intern (":bounding-box");
+ QCbounding_box = intern_c_string (":bounding-box");
staticpro (&QCbounding_box);
- QCpt_width = intern (":pt-width");
+ QCpt_width = intern_c_string (":pt-width");
staticpro (&QCpt_width);
- QCpt_height = intern (":pt-height");
+ QCpt_height = intern_c_string (":pt-height");
staticpro (&QCpt_height);
#endif /* HAVE_GHOSTSCRIPT */
#if defined (HAVE_XPM) || defined (HAVE_NS)
- Qxpm = intern ("xpm");
+ Qxpm = intern_c_string ("xpm");
staticpro (&Qxpm);
ADD_IMAGE_TYPE (Qxpm);
#endif
#if defined (HAVE_JPEG) || defined (HAVE_NS)
- Qjpeg = intern ("jpeg");
+ Qjpeg = intern_c_string ("jpeg");
staticpro (&Qjpeg);
ADD_IMAGE_TYPE (Qjpeg);
#endif
#if defined (HAVE_TIFF) || defined (HAVE_NS)
- Qtiff = intern ("tiff");
+ Qtiff = intern_c_string ("tiff");
staticpro (&Qtiff);
ADD_IMAGE_TYPE (Qtiff);
#endif
#if defined (HAVE_GIF) || defined (HAVE_NS)
- Qgif = intern ("gif");
+ Qgif = intern_c_string ("gif");
staticpro (&Qgif);
ADD_IMAGE_TYPE (Qgif);
#endif
#if defined (HAVE_PNG) || defined (HAVE_NS)
- Qpng = intern ("png");
+ Qpng = intern_c_string ("png");
staticpro (&Qpng);
ADD_IMAGE_TYPE (Qpng);
#endif
#if defined (HAVE_RSVG)
- Qsvg = intern ("svg");
+ Qsvg = intern_c_string ("svg");
staticpro (&Qsvg);
ADD_IMAGE_TYPE (Qsvg);
#ifdef HAVE_NTGUI
- Qgdk_pixbuf = intern ("gdk-pixbuf");
+ /* Other libraries used directly by svg code. */
+ Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
staticpro (&Qgdk_pixbuf);
- Qglib = intern ("glib");
+ Qglib = intern_c_string ("glib");
staticpro (&Qglib);
+ Qgobject = intern_c_string ("gobject");
+ staticpro (&Qgobject);
#endif /* HAVE_NTGUI */
#endif /* HAVE_RSVG */
defsubr (&Sinit_image_library);
defsubr (&Sclear_image_cache);
- defsubr (&Simage_refresh);
+ defsubr (&Simage_flush);
defsubr (&Simage_size);
defsubr (&Simage_mask_p);
- defsubr (&Simage_extension_data);
+ defsubr (&Simage_metadata);
#if GLYPH_DEBUG
defsubr (&Simagep);
Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
- doc: /* Time after which cached images are removed from the cache.
-When an image has not been displayed this many seconds, remove it
-from the image cache. Value must be an integer or nil with nil
-meaning don't clear the cache. */);
- Vimage_cache_eviction_delay = make_number (30 * 60);
+ doc: /* Maximum time after which images are removed from the cache.
+When an image has not been displayed this many seconds, Emacs
+automatically removes it from the image cache. If the cache contains
+a large number of images, the actual eviction time may be shorter.
+The value can also be nil, meaning the cache is never cleared.
+
+The function `clear-image-cache' disregards this variable. */);
+ Vimage_cache_eviction_delay = make_number (300);
}
void