#ifdef HAVE_NTGUI
+#include "w32.h"
#include "w32term.h"
/* W32_TODO : Color tables on W32. */
/* The symbol `postscript' identifying images of this type. */
-Lisp_Object Qpostscript;
+static Lisp_Object Qpostscript;
static void x_disable_image (struct frame *, struct image *);
static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
static unsigned long *colors_in_color_table (int *n);
static unsigned long lookup_pixel_color (struct frame *f, unsigned long p);
#endif
+static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object);
/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
id, which is just an int that this section returns. Bitmaps are
static struct image_type *image_types;
-/* Cache for delayed-loading image types. */
-
-static Lisp_Object Vimage_type_cache;
-
/* The symbol `xbm' which is used as the type symbol for XBM images. */
-Lisp_Object Qxbm;
+static Lisp_Object Qxbm;
/* Keywords. */
-Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data;
-Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation;
+Lisp_Object QCascent, QCmargin, QCrelief;
+static Lisp_Object Qcount, Qextension_data;
+Lisp_Object QCconversion;
+static Lisp_Object QCheuristic_mask;
+static Lisp_Object QCcolor_symbols;
+static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
+static Lisp_Object QCcrop, QCrotation;
/* Other symbols. */
-Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
+static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
/* Function prototypes. */
static void x_emboss (struct frame *, struct image *);
static int x_build_heuristic_mask (struct frame *, struct image *,
Lisp_Object);
-
+#ifdef HAVE_NTGUI
#define CACHE_IMAGE_TYPE(type, status) \
- do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
+ do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
+#else
+#define CACHE_IMAGE_TYPE(type, status)
+#endif
#define ADD_IMAGE_TYPE(type) \
do { Vimage_types = Fcons (type, Vimage_types); } while (0)
/* Look up image type SYMBOL, and return a pointer to its image_type
structure. Value is null if SYMBOL is not a known image type. */
-static INLINE struct image_type *
+static inline struct image_type *
lookup_image_type (Lisp_Object symbol)
{
struct image_type *type;
case IMAGE_FUNCTION_VALUE:
value = indirect_function (value);
- if (SUBRP (value)
- || COMPILEDP (value)
- || (CONSP (value) && EQ (XCAR (value), Qlambda)))
+ if (!NILP (Ffunctionp (value)))
break;
return 0;
Image type independent image structures
***********************************************************************/
-static struct image *make_image (Lisp_Object spec, unsigned hash);
static void free_image (struct frame *f, struct image *img);
static int check_image_size (struct frame *f, int width, int height);
SPEC. SPEC has a hash value of HASH. */
static struct image *
-make_image (Lisp_Object spec, unsigned int hash)
+make_image (Lisp_Object spec, EMACS_UINT hash)
{
struct image *img = (struct image *) xmalloc (sizeof *img);
Lisp_Object file = image_spec_value (spec, QCfile, NULL);
four_corners_best (XImagePtr_or_DC ximg, int *corners,
unsigned long width, unsigned long height)
{
- RGB_PIXEL_COLOR corner_pixels[4], best;
+ RGB_PIXEL_COLOR corner_pixels[4], best IF_LINT (= 0);
int i, best_count;
if (corners && corners[BOT_CORNER] >= 0)
Image Cache
***********************************************************************/
-static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
static void cache_image (struct frame *f, struct image *img);
static void postprocess_image (struct frame *, struct image *);
/* Find an image matching SPEC in the cache, and return it. If no
image is found, return NULL. */
static struct image *
-search_image_cache (struct frame *f, Lisp_Object spec, unsigned int hash)
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
{
struct image *img;
struct image_cache *c = FRAME_IMAGE_CACHE (f);
{
/* Free cache based on timestamp. */
EMACS_TIME t;
- unsigned long old;
+ time_t old;
int delay, nimages = 0;
for (i = 0; i < c->used; ++i)
FOR_EACH_FRAME (tail, frame)
{
- struct frame *f = XFRAME (frame);
- if (FRAME_IMAGE_CACHE (f) == c)
- clear_current_matrices (f);
+ struct frame *fr = XFRAME (frame);
+ if (FRAME_IMAGE_CACHE (fr) == c)
+ clear_current_matrices (fr);
}
++windows_or_buffers_changed;
int
lookup_image (struct frame *f, Lisp_Object spec)
{
- struct image_cache *c;
struct image *img;
- unsigned hash;
+ EMACS_UINT hash;
EMACS_TIME now;
/* F must be a window-system frame, and SPEC must be a valid image
xassert (FRAME_WINDOW_P (f));
xassert (valid_image_p (spec));
- c = FRAME_IMAGE_CACHE (f);
-
/* Look up SPEC in the hash table of the image cache. */
hash = sxhash (spec, 0);
img = search_image_cache (f, spec, hash);
#ifdef HAVE_NTGUI
/* Macro for defining functions that will be loaded from image DLLs. */
-#define DEF_IMGLIB_FN(rettype,func,args) rettype (FAR CDECL *fn_##func)args
+#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
/* Macro for loading those image functions from the library. */
#define LOAD_IMGLIB_FN(lib,func) { \
if (!fn_##func) return 0; \
}
-/* Load a DLL implementing an image type.
- The argument LIBRARIES is usually the variable
- `dynamic-library-alist', which associates a symbol, identifying
- an external DLL library, to a list of possible filenames.
- The function returns NULL if no library could be loaded for
- the given symbol, or if the library was previously loaded;
- else the handle of the DLL. */
-static HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
-{
- HMODULE library = NULL;
-
- if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
- {
- Lisp_Object dlls = Fassq (type, libraries);
-
- if (CONSP (dlls))
- for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
- {
- CHECK_STRING_CAR (dlls);
- if (library = LoadLibrary (SDATA (XCAR (dlls))))
- break;
- }
- }
-
- return library;
-}
-
#endif /* HAVE_NTGUI */
static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
File Handling
***********************************************************************/
-static unsigned char *slurp_file (char *, int *);
-
-
/* Find image file FILE. Look in data-directory/images, then
x-bitmap-file-path. Value is the encoded full name of the file
found, or nil if not found. */
occurred. *SIZE is set to the size of the file. */
static unsigned char *
-slurp_file (char *file, int *size)
+slurp_file (char *file, ptrdiff_t *size)
{
FILE *fp = NULL;
unsigned char *buf = NULL;
if (stat (file, &st) == 0
&& (fp = fopen (file, "rb")) != NULL
+ && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
&& (buf = (unsigned char *) xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
int i;
/* Number of elements of the vector must be >= height. */
- if (XVECTOR (data)->size < height)
+ if (ASIZE (data) < height)
return 0;
/* Each string or bool-vector in data must be large enough
if (LA1 == XBM_TK_NUMBER)
{
- char *p = strrchr (buffer, '_');
- p = p ? p + 1 : buffer;
- if (strcmp (p, "width") == 0)
+ char *q = strrchr (buffer, '_');
+ q = q ? q + 1 : buffer;
+ if (strcmp (q, "width") == 0)
*width = value;
- else if (strcmp (p, "height") == 0)
+ else if (strcmp (q, "height") == 0)
*height = value;
}
expect (XBM_TK_NUMBER);
{
Lisp_Object file;
unsigned char *contents;
- int size;
+ ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
/* Parse the image specification. */
memcpy (fmt, xbm_format, sizeof fmt);
parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
+ (void) parsed_p;
xassert (parsed_p);
/* Get specified width, and height. */
#if defined (HAVE_XPM) || defined (HAVE_NS)
/* The symbol `xpm' identifying XPM-format images. */
-Lisp_Object Qxpm;
+static Lisp_Object Qxpm;
/* Indices of image specification fields in xpm_format, below. */
size. */
#define XPM_COLOR_CACHE_BUCKETS 1001
-struct xpm_cached_color **xpm_color_cache;
+static struct xpm_cached_color **xpm_color_cache;
/* Initialize the color cache. */
#endif /* HAVE_XPM || HAVE_NS */
-#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
int
x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
{
Lisp_Object color)
{
struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
- unsigned hash_code;
+ EMACS_UINT hash_code;
Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
hash_lookup (table, chars, &hash_code);
{
Lisp_Object file;
unsigned char *contents;
- int size;
+ ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
/* The color hash table. */
-struct ct_color **ct_table;
+static struct ct_color **ct_table;
/* Number of entries in the color table. */
-int ct_colors_allocated;
+static int ct_colors_allocated;
/* Initialize the color table. */
XPutPixel (XImagePtr ximg, int x, int y, COLORREF color)
{
int width = ximg->info.bmiHeader.biWidth;
- int height = ximg->info.bmiHeader.biHeight;
unsigned char * pixel;
/* True color images. */
for (x = 1; x < img->width - 1; ++x, ++p)
{
- int r, g, b, y1, x1;
+ int r, g, b, yy, xx;
r = g = b = i = 0;
- for (y1 = y - 1; y1 < y + 2; ++y1)
- for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+ for (yy = y - 1; yy < y + 2; ++yy)
+ for (xx = x - 1; xx < x + 2; ++xx, ++i)
if (matrix[i])
{
- XColor *t = COLOR (colors, x1, y1);
+ XColor *t = COLOR (colors, xx, yy);
r += matrix[i] * t->red;
g += matrix[i] * t->green;
b += matrix[i] * t->blue;
/* The symbol `pbm' identifying images of this type. */
-Lisp_Object Qpbm;
+static Lisp_Object Qpbm;
/* Indices of image specification fields in gs_format, below. */
if (stat (SDATA (file), &st) == 0
&& (fp = fopen (SDATA (file), "rb")) != NULL
+ && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
&& (buf = (char *) xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
unsigned char *contents = NULL;
unsigned char *end, *p;
- int size;
+ ptrdiff_t size;
specified_file = image_spec_value (img->spec, QCfile, NULL);
/* The symbol `png' identifying images of this type. */
-Lisp_Object Qpng;
+static Lisp_Object Qpng;
/* Indices of image specification fields in png_format, below. */
{
HMODULE library;
- /* Try loading libpng under probable names. */
if (!(library = w32_delayed_load (libraries, Qpng)))
return 0;
/* Error and warning handlers installed when the PNG library
is initialized. */
+static void my_png_error (png_struct *, const char *) NO_RETURN;
static void
my_png_error (png_struct *png_ptr, const char *msg)
{
/* The symbol `jpeg' identifying images of this type. */
-Lisp_Object Qjpeg;
+static Lisp_Object Qjpeg;
/* Indices of image specification fields in gs_format, below. */
};
+static void my_error_exit (j_common_ptr) NO_RETURN;
static void
my_error_exit (j_common_ptr cinfo)
{
if (rc == 1)
{
/* Called from my_error_exit. Display a JPEG error. */
- char buffer[JMSG_LENGTH_MAX];
- cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
+ char buf[JMSG_LENGTH_MAX];
+ cinfo.err->format_message ((j_common_ptr) &cinfo, buf);
image_error ("Error reading JPEG image `%s': %s", img->spec,
- build_string (buffer));
+ build_string (buf));
}
/* Close the input file and destroy the JPEG object. */
/* The symbol `tiff' identifying images of this type. */
-Lisp_Object Qtiff;
+static Lisp_Object Qtiff;
/* Indices of image specification fields in tiff_format, below. */
}
+static void tiff_error_handler (const char *, const char *, va_list)
+ ATTRIBUTE_FORMAT_PRINTF (2, 0);
static void
tiff_error_handler (const char *title, const char *format, va_list ap)
{
}
+static void tiff_warning_handler (const char *, const char *, va_list)
+ ATTRIBUTE_FORMAT_PRINTF (2, 0);
static void
tiff_warning_handler (const char *title, const char *format, va_list ap)
{
TIFF *tiff;
int width, height, x, y, count;
uint32 *buf;
- int rc, rc2;
+ int rc;
XImagePtr ximg;
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);
- fn_TIFFSetErrorHandler (tiff_error_handler);
- fn_TIFFSetWarningHandler (tiff_warning_handler);
+ fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
+ fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
if (NILP (specified_data))
{
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);
+ for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
+ continue;
if (count > 1)
img->data.lisp_val = Fcons (Qcount,
/* The symbol `gif' identifying images of this type. */
-Lisp_Object Qgif;
+static Lisp_Object Qgif;
/* Indices of image specification fields in gif_format, below. */
static int
gif_load (struct frame *f, struct image *img)
{
- Lisp_Object file, specified_file;
- Lisp_Object specified_data;
- int rc, width, height, x, y, i;
- boolean transparent_p;
+ Lisp_Object file;
+ int rc, width, height, x, y, i, j;
XImagePtr ximg;
ColorMapObject *gif_color_map;
unsigned long pixel_colors[256];
GifFileType *gif;
- Lisp_Object image;
- int ino, image_height, image_width;
+ int image_height, image_width;
gif_memory_source memsrc;
- unsigned char *raster;
- unsigned int transparency_color_index;
-
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- specified_data = image_spec_value (img->spec, QCdata, NULL);
+ Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+ Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
+ Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
+ unsigned long bgcolor = 0;
+ int idx;
if (NILP (specified_data))
{
/* Read entire contents. */
rc = fn_DGifSlurp (gif);
- if (rc == GIF_ERROR)
+ if (rc == GIF_ERROR || gif->ImageCount <= 0)
{
image_error ("Error reading `%s'", img->spec, Qnil);
fn_DGifCloseFile (gif);
return 0;
}
- image = image_spec_value (img->spec, QCindex, NULL);
- ino = INTEGERP (image) ? XFASTINT (image) : 0;
- if (ino >= gif->ImageCount)
- {
- image_error ("Invalid image number `%s' in image `%s'",
- image, img->spec);
- fn_DGifCloseFile (gif);
- return 0;
- }
-
- for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++)
- if ((gif->SavedImages[ino].ExtensionBlocks[i].Function
- == GIF_LOCAL_DESCRIPTOR_EXTENSION)
- && gif->SavedImages[ino].ExtensionBlocks[i].ByteCount == 4
- /* Transparency enabled? */
- && gif->SavedImages[ino].ExtensionBlocks[i].Bytes[0] & 1)
+ /* Which sub-image are we to display? */
+ {
+ Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
+ idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
+ if (idx < 0 || idx >= gif->ImageCount)
{
- transparent_p = 1;
- transparency_color_index
- = (unsigned char) gif->SavedImages[ino].ExtensionBlocks[i].Bytes[3];
+ image_error ("Invalid image number `%s' in image `%s'",
+ image_number, img->spec);
+ fn_DGifCloseFile (gif);
+ return 0;
}
+ }
- img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
- img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
- image_height = gif->SavedImages[ino].ImageDesc.Height;
+ img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
+ img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
+ image_height = gif->SavedImages[idx].ImageDesc.Height;
img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
- image_width = gif->SavedImages[ino].ImageDesc.Width;
+ image_width = gif->SavedImages[idx].ImageDesc.Width;
img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
width = img->width = max (gif->SWidth,
return 0;
}
- /* Allocate colors. */
- gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
- if (!gif_color_map)
- gif_color_map = gif->SColorMap;
- init_color_table ();
- memset (pixel_colors, 0, sizeof pixel_colors);
-
- if (gif_color_map)
- for (i = 0; i < gif_color_map->ColorCount; ++i)
- {
- if (transparent_p && transparency_color_index == i)
- {
- Lisp_Object specified_bg
- = image_spec_value (img->spec, QCbackground, NULL);
- pixel_colors[i] = STRINGP (specified_bg)
- ? x_alloc_image_color (f, img, specified_bg,
- FRAME_BACKGROUND_PIXEL (f))
- : FRAME_BACKGROUND_PIXEL (f);
- }
- else
- {
- int r = gif_color_map->Colors[i].Red << 8;
- int g = gif_color_map->Colors[i].Green << 8;
- int b = gif_color_map->Colors[i].Blue << 8;
- pixel_colors[i] = lookup_rgb_color (f, r, g, b);
- }
- }
-
-#ifdef COLOR_TABLE_SUPPORT
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
-
- /* Clear the part of the screen image that are not covered by
- the image from the GIF file. Full animated GIF support
- requires more than can be done here (see the gif89 spec,
- disposal methods). Let's simply assume that the part
- not covered by a sub-image is in the frame's background color. */
+ /* Clear the part of the screen image not covered by the image.
+ Full animated GIF support requires more here (see the gif89 spec,
+ disposal methods). Let's simply assume that the part not covered
+ by a sub-image is in the frame's background color. */
for (y = 0; y < img->corners[TOP_CORNER]; ++y)
for (x = 0; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
- /* Read the GIF image into the X image. We use a local variable
- `raster' here because RasterBits below is a char *, and invites
- problems with bytes >= 0x80. */
- raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+ /* Read the GIF image into the X image. */
- if (gif->SavedImages[ino].ImageDesc.Interlace)
- {
- int pass;
- int row = interlace_start[0];
-
- pass = 0;
+ /* FIXME: With the current implementation, loading an animated gif
+ is quadratic in the number of animation frames, since each frame
+ is a separate struct image. We must provide a way for a single
+ gif_load call to construct and save all animation frames. */
- for (y = 0; y < image_height; y++)
+ init_color_table ();
+ if (STRINGP (specified_bg))
+ bgcolor = x_alloc_image_color (f, img, specified_bg,
+ FRAME_BACKGROUND_PIXEL (f));
+ for (j = 0; j <= idx; ++j)
+ {
+ /* We use a local variable `raster' here because RasterBits is a
+ char *, which invites problems with bytes >= 0x80. */
+ struct SavedImage *subimage = gif->SavedImages + j;
+ unsigned char *raster = (unsigned char *) subimage->RasterBits;
+ int transparency_color_index = -1;
+ int disposal = 0;
+
+ /* Find the Graphic Control Extension block for this sub-image.
+ Extract the disposal method and transparency color. */
+ for (i = 0; i < subimage->ExtensionBlockCount; i++)
{
- if (row >= image_height)
- {
- row = interlace_start[++pass];
- while (row >= image_height)
- row = interlace_start[++pass];
- }
+ ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
- for (x = 0; x < image_width; x++)
+ if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
+ && extblock->ByteCount == 4
+ && extblock->Bytes[0] & 1)
{
- int i = raster[(y * image_width) + x];
- XPutPixel (ximg, x + img->corners[LEFT_CORNER],
- row + img->corners[TOP_CORNER], pixel_colors[i]);
+ /* From gif89a spec: 1 = "keep in place", 2 = "restore
+ to background". Treat any other value like 2. */
+ disposal = (extblock->Bytes[0] >> 2) & 7;
+ transparency_color_index = (unsigned char) extblock->Bytes[3];
+ break;
}
-
- row += interlace_increment[pass];
}
- }
- else
- {
- for (y = 0; y < image_height; ++y)
- for (x = 0; x < image_width; ++x)
+
+ /* We can't "keep in place" the first subimage. */
+ if (j == 0)
+ disposal = 2;
+
+ /* Allocate subimage colors. */
+ memset (pixel_colors, 0, sizeof pixel_colors);
+ gif_color_map = subimage->ImageDesc.ColorMap;
+ if (!gif_color_map)
+ gif_color_map = gif->SColorMap;
+
+ if (gif_color_map)
+ for (i = 0; i < gif_color_map->ColorCount; ++i)
{
- int i = raster[y * image_width + x];
- XPutPixel (ximg, x + img->corners[LEFT_CORNER],
- y + img->corners[TOP_CORNER], pixel_colors[i]);
+ if (transparency_color_index == i)
+ pixel_colors[i] = STRINGP (specified_bg)
+ ? bgcolor : FRAME_BACKGROUND_PIXEL (f);
+ else
+ {
+ int r = gif_color_map->Colors[i].Red << 8;
+ int g = gif_color_map->Colors[i].Green << 8;
+ int b = gif_color_map->Colors[i].Blue << 8;
+ pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+ }
}
+
+ /* Apply the pixel values. */
+ if (gif->SavedImages[j].ImageDesc.Interlace)
+ {
+ int row, pass;
+
+ for (y = 0, row = interlace_start[0], pass = 0;
+ y < image_height;
+ y++, row += interlace_increment[pass])
+ {
+ if (row >= image_height)
+ {
+ row = interlace_start[++pass];
+ while (row >= image_height)
+ row = interlace_start[++pass];
+ }
+
+ for (x = 0; x < image_width; x++)
+ {
+ int c = raster[y * image_width + x];
+ if (transparency_color_index != c || disposal != 1)
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ row + img->corners[TOP_CORNER], pixel_colors[c]);
+ }
+ }
+ }
+ else
+ {
+ for (y = 0; y < image_height; ++y)
+ for (x = 0; x < image_width; ++x)
+ {
+ int c = raster[y * image_width + x];
+ if (transparency_color_index != c || disposal != 1)
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ y + img->corners[TOP_CORNER], pixel_colors[c]);
+ }
+ }
}
+#ifdef COLOR_TABLE_SUPPORT
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
/* 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)
+ if (gif->SavedImages[idx].ExtensionBlockCount > 0)
{
- ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
- for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+ ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
+ for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
/* Append (... FUNCTION "BYTES") */
img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
Fcons (make_number (ext->Function),
/***********************************************************************
- imagemagick
+ ImageMagick
***********************************************************************/
#if defined (HAVE_IMAGEMAGICK)
-/* The symbol `imagemagick' identifying images of this type. */
-
Lisp_Object Qimagemagick;
-/* Indices of image specification fields in imagemagick_format, below. */
+
+static int imagemagick_image_p (Lisp_Object);
+static int imagemagick_load (struct frame *, struct image *);
+static void imagemagick_clear_image (struct frame *, struct image *);
+
+/* Indices of image specification fields in imagemagick_format. */
enum imagemagick_keyword_index
{
{":rotation", IMAGE_NUMBER_VALUE, 0},
{":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
+
+/* Structure describing the image type for any image handled via
+ ImageMagick. */
+
+static struct image_type imagemagick_type =
+ {
+ &Qimagemagick,
+ imagemagick_image_p,
+ imagemagick_load,
+ imagemagick_clear_image,
+ NULL
+ };
+
/* Free X resources of imagemagick image IMG which is used on frame F. */
static void
x_clear_image (f, img);
}
-
-
/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do
this by calling parse_image_spec and supplying the keywords that
identify the IMAGEMAGICK format. */
#define DrawRectangle DrawRectangleGif
#include <wand/MagickWand.h>
-/* imagemagick_load_image is a helper function for imagemagick_load,
- which does the actual loading given contents and size, apart from
- frame and image structures, passed from imagemagick_load.
+/* Helper function for imagemagick_load, which does the actual loading
+ given contents and size, apart from frame and image structures,
+ passed from imagemagick_load. Uses librimagemagick to do most of
+ the image processing.
- Uses librimagemagick to do most of the image processing.
+ F is a pointer to the Emacs frame; IMG to the image structure to
+ prepare; CONTENTS is the string containing the IMAGEMAGICK data to
+ be parsed; SIZE is the number of bytes of data; and FILENAME is
+ either the file name or the image data.
- non-zero when successful.
-*/
+ Return non-zero if successful. */
static int
-imagemagick_load_image (/* Pointer to emacs frame structure. */
- struct frame *f,
- /* Pointer to emacs image structure. */
- struct image *img,
- /* String containing the IMAGEMAGICK data to
- be parsed. */
- unsigned char *contents,
- /* Size of data in bytes. */
- unsigned int size,
- /* Filename, either pass filename or
- contents/size. */
- unsigned char *filename)
+imagemagick_load_image (struct frame *f, struct image *img,
+ unsigned char *contents, unsigned int size,
+ char *filename)
{
unsigned long width;
unsigned long height;
- MagickBooleanType
- status;
+ MagickBooleanType status;
XImagePtr ximg;
- Lisp_Object specified_bg;
- XColor background;
int x;
int y;
MagickPixelPacket pixel;
Lisp_Object image;
Lisp_Object value;
- Lisp_Object crop, geometry;
+ Lisp_Object crop;
long ino;
int desired_width, desired_height;
double rotation;
Image * im_image;
- /* Handle image index for image types who can contain more than one
- image. Interface :index is same as for GIF. First we "ping" the
- image to see how many sub-images it contains. Pinging is faster
- than loading the image to find out things about it. */
+ /* Handle image index for image types who can contain more than one image.
+ Interface :index is same as for GIF. First we "ping" the image to see how
+ many sub-images it contains. Pinging is faster than loading the image to
+ find out things about it. */
- /* `MagickWandGenesis' initializes the imagemagick environment. */
+ /* Initialize the imagemagick environment. */
MagickWandGenesis ();
image = image_spec_value (img->spec, QCindex, NULL);
ino = INTEGERP (image) ? XFASTINT (image) : 0;
DestroyMagickWand (ping_wand);
- /* Now, after pinging, we know how many images are inside the
- file. If its not a bundle, just one. */
+ /* Now we know how many images are inside the file. If it's not a
+ bundle, the number is one. */
if (filename != NULL)
{
im_image = ReadImage (image_info, exception);
DestroyExceptionInfo (exception);
- if (im_image != NULL)
- {
- image_wand = NewMagickWandFromImage (im_image);
- DestroyImage(im_image);
- status = MagickTrue;
- }
- else
- status = MagickFalse;
+ if (im_image == NULL)
+ goto imagemagick_no_wand;
+ image_wand = NewMagickWandFromImage (im_image);
+ DestroyImage(im_image);
}
else
{
image_wand = NewMagickWand ();
- status = MagickReadImageBlob (image_wand, contents, size);
+ if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
+ goto imagemagick_error;
}
- if (status == MagickFalse) goto imagemagick_error;
-
/* If width and/or height is set in the display spec assume we want
- to scale to those values. if either h or w is unspecified, the
+ to scale to those values. If either h or w is unspecified, the
unspecified should be calculated from the specified to preserve
aspect ratio. */
height = MagickGetImageHeight (image_wand);
width = MagickGetImageWidth (image_wand);
- if(desired_width != -1 && desired_height == -1)
- {
- /* w known, calculate h. */
- desired_height = (double) desired_width / width * height;
- }
- if(desired_width == -1 && desired_height != -1)
- {
- /* h known, calculate w. */
- desired_width = (double) desired_height / height * width;
- }
- if(desired_width != -1 && desired_height != -1)
+ if (desired_width != -1 && desired_height == -1)
+ /* w known, calculate h. */
+ desired_height = (double) desired_width / width * height;
+ if (desired_width == -1 && desired_height != -1)
+ /* h known, calculate w. */
+ desired_width = (double) desired_height / height * width;
+ if (desired_width != -1 && desired_height != -1)
{
status = MagickScaleImage (image_wand, desired_width, desired_height);
if (status == MagickFalse)
}
}
-
/* crop behaves similar to image slicing in Emacs but is more memory
efficient. */
crop = image_spec_value (img->spec, QCcrop, NULL);
if (CONSP (crop) && INTEGERP (XCAR (crop)))
{
- /* After some testing, it seems MagickCropImage is the fastest
- crop function in ImageMagick. This crop function seems to do
- less copying than the alternatives, but it still reads the
- entire image into memory before croping, which is aparently
- difficult to avoid when using imagemagick. */
-
- int w, h, x, y;
+ /* After some testing, it seems MagickCropImage is the fastest crop
+ function in ImageMagick. This crop function seems to do less copying
+ than the alternatives, but it still reads the entire image into memory
+ before croping, which is aparently difficult to avoid when using
+ imagemagick. */
+ int w, h;
w = XFASTINT (XCAR (crop));
crop = XCDR (crop);
if (CONSP (crop) && INTEGERP (XCAR (crop)))
}
}
- /* Finaly we are done manipulating the image, figure out resulting
- width, height, and then transfer ownerwship to Emacs. */
+ /* Finally we are done manipulating the image. Figure out the
+ resulting width/height and transfer ownerwship to Emacs. */
height = MagickGetImageHeight (image_wand);
width = MagickGetImageWidth (image_wand);
method is also well tested. Some aspects of this method are
ad-hoc and needs to be more researched. */
int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
- char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
+ const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
/* Try to create a x pixmap to hold the imagemagick pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
&ximg, &img->pixmap))
imagemagick_error:
DestroyMagickWand (image_wand);
+ imagemagick_no_wand:
MagickWandTerminus ();
/* TODO more cleanup. */
image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
the prototype thus needs to be compatible with that structure. */
static int
-imagemagick_load (struct frame *f,
- struct image *img)
+imagemagick_load (struct frame *f, struct image *img)
{
int success_p = 0;
Lisp_Object file_name;
image_error ("Cannot find image file `%s'", file_name, Qnil);
return 0;
}
- success_p = imagemagick_load_image (f, img, 0, 0, SDATA (file));
+ 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
lisp object rather than a file. */
return success_p;
}
-/* Structure describing the image type `imagemagick'. Its the same
- type of structure defined for all image formats, handled by Emacs
- image functions. See struct image_type in dispextern.h. */
-
-static struct image_type imagemagick_type =
- {
- /* An identifier showing that this is an image structure for the
- IMAGEMAGICK format. */
- &Qimagemagick,
- /* Handle to a function that can be used to identify a IMAGEMAGICK
- file. */
- imagemagick_image_p,
- /* Handle to function used to load a IMAGEMAGICK file. */
- imagemagick_load,
- /* Handle to function to free resources for IMAGEMAGICK. */
- imagemagick_clear_image,
- /* An internal field to link to the next image type in a list of
- image types, will be filled in when registering the format. */
- NULL
- };
-
-
-
-
DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
- doc: /* Return image file types supported by ImageMagick.
-Since ImageMagick recognizes a lot of file-types that clash with Emacs,
-such as .c, we want to be able to alter the list at the lisp level. */)
+ doc: /* Return a list of image types supported by ImageMagick.
+Each entry in this list is a symbol named after an ImageMagick format
+tag. See the ImageMagick manual for a list of ImageMagick formats and
+their descriptions (http://www.imagemagick.org/script/formats.php).
+
+Note that ImageMagick recognizes many file-types that Emacs does not
+recognize as images, such as C. See `imagemagick-types-inhibit'. */)
(void)
{
Lisp_Object typelist = Qnil;
- unsigned long numf;
+ unsigned long numf = 0;
ExceptionInfo ex;
char **imtypes = GetMagickList ("*", &numf, &ex);
int i;
static int svg_load (struct frame *f, struct image *img);
static int svg_load_image (struct frame *, struct image *,
- unsigned char *, unsigned int);
+ unsigned char *, ptrdiff_t);
/* The symbol `svg' identifying images of this type. */
DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
-DEF_IMGLIB_FN (void, rsvg_handle_free);
DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
LOAD_IMGLIB_FN (library, rsvg_handle_write);
LOAD_IMGLIB_FN (library, rsvg_handle_close);
LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
- LOAD_IMGLIB_FN (library, rsvg_handle_free);
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
#define fn_rsvg_handle_write rsvg_handle_write
#define fn_rsvg_handle_close rsvg_handle_close
#define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
-#define fn_rsvg_handle_free rsvg_handle_free
#define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
#define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
{
Lisp_Object file;
unsigned char *contents;
- int size;
+ ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
}
/* Read the entire file into memory. */
- contents = slurp_file (SDATA (file), &size);
+ contents = slurp_file (SSDATA (file), &size);
if (contents == NULL)
{
image_error ("Error loading SVG image `%s'", img->spec, Qnil);
svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
struct image *img, /* Pointer to emacs image structure. */
unsigned char *contents, /* String containing the SVG XML data to be parsed. */
- unsigned int size) /* Size of data in bytes. */
+ ptrdiff_t size) /* Size of data in bytes. */
{
RsvgHandle *rsvg_handle;
RsvgDimensionData dimension_data;
- GError *error = NULL;
+ GError *err = NULL;
GdkPixbuf *pixbuf;
int width;
int height;
rsvg_handle = fn_rsvg_handle_new ();
/* Parse the contents argument and fill in the rsvg_handle. */
- fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
- if (error) goto rsvg_error;
+ fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+ if (err) goto rsvg_error;
/* The parsing is complete, rsvg_handle is ready to used, close it
for further writes. */
- fn_rsvg_handle_close (rsvg_handle, &error);
- if (error) goto rsvg_error;
+ fn_rsvg_handle_close (rsvg_handle, &err);
+ if (err) goto rsvg_error;
fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
if (! check_image_size (f, dimension_data.width, dimension_data.height))
color. */
specified_bg = image_spec_value (img->spec, QCbackground, NULL);
if (!STRINGP (specified_bg)
- || !x_defined_color (f, SDATA (specified_bg), &background, 0))
+ || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
{
#ifndef HAVE_NS
background.pixel = FRAME_BACKGROUND_PIXEL (f);
/* FIXME: Use error->message so the user knows what is the actual
problem with the image. */
image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
- fn_g_error_free (error);
+ fn_g_error_free (err);
return 0;
}
/* Keyword symbols. */
-Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
+static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
/* Indices of image specification fields in gs_format, below. */
}
else if (VECTORP (tem))
{
- if (XVECTOR (tem)->size != 4)
+ if (ASIZE (tem) != 4)
return 0;
for (i = 0; i < 4; ++i)
if (!INTEGERP (XVECTOR (tem)->contents[i]))
of `dynamic-library-alist', which see). */)
(Lisp_Object type, Lisp_Object libraries)
{
- Lisp_Object tested;
-
+#ifdef HAVE_NTGUI
/* Don't try to reload the library. */
- tested = Fassq (type, Vimage_type_cache);
+ Lisp_Object tested = Fassq (type, Vlibrary_cache);
if (CONSP (tested))
return XCDR (tested);
+#endif
+
+ /* Types pbm and xbm are built-in and always available. */
+ if (EQ (type, Qpbm) || EQ (type, Qxbm))
+ return Qt;
#if defined (HAVE_XPM) || defined (HAVE_NS)
if (EQ (type, Qxpm))
#if defined (HAVE_IMAGEMAGICK)
if (EQ (type, Qimagemagick))
- {
- return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
- libraries);
- }
+ return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
+ libraries);
#endif
#ifdef HAVE_GHOSTSCRIPT
non-numeric, there is no explicit limit on the size of images. */);
Vmax_image_size = make_float (MAX_IMAGE_SIZE);
- Vimage_type_cache = Qnil;
- staticpro (&Vimage_type_cache);
-
Qpbm = intern_c_string ("pbm");
staticpro (&Qpbm);
ADD_IMAGE_TYPE (Qpbm);