/* Functions for image support on window system.
- Copyright (C) 1989, 1992-2011 Free Software Foundation, Inc.
+
+Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#define COLOR_TABLE_SUPPORT 1
typedef struct x_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
#define NO_PIXMAP None
#define RGB_PIXEL_COLOR unsigned long
#undef COLOR_TABLE_SUPPORT
typedef struct w32_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y)
#define NO_PIXMAP 0
#define RGB_PIXEL_COLOR COLORREF
typedef struct ns_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
#define NO_PIXMAP 0
#define RGB_PIXEL_COLOR unsigned long
#define PIX_MASK_RETAIN 0
#define PIX_MASK_DRAW 1
-#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
+#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO (f)->visual
#define x_defined_color(f, name, color_def, alloc) \
ns_defined_color (f, name, color_def, alloc, 0)
#define FRAME_X_SCREEN(f) 0
static void free_color_table (void);
static unsigned long *colors_in_color_table (int *n);
#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
int
x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
{
+ /* HAVE_NTGUI needs the explicit cast here. */
return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
}
#endif
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
ptrdiff_t i;
- if (dpyinfo->bitmaps == NULL)
- {
- dpyinfo->bitmaps_size = 10;
- dpyinfo->bitmaps
- = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
- dpyinfo->bitmaps_last = 1;
- return 1;
- }
-
if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
return ++dpyinfo->bitmaps_last;
if (dpyinfo->bitmaps[i].refcount == 0)
return i + 1;
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2
- < dpyinfo->bitmaps_size)
- memory_full (SIZE_MAX);
- dpyinfo->bitmaps_size *= 2;
- dpyinfo->bitmaps
- = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
- dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
+ dpyinfo->bitmaps =
+ xpalloc (dpyinfo->bitmaps, &dpyinfo->bitmaps_size,
+ 10, -1, sizeof *dpyinfo->bitmaps);
return ++dpyinfo->bitmaps_last;
}
/* Add one reference to the reference count of the bitmap with id ID. */
void
-x_reference_bitmap (FRAME_PTR f, int id)
+x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
{
++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
}
id = x_allocate_bitmap_record (f);
dpyinfo->bitmaps[id - 1].img = bitmap;
dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
+ dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1);
dpyinfo->bitmaps[id - 1].depth = 1;
dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap);
dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap);
dpyinfo->bitmaps[id - 1].pixmap = bitmap;
dpyinfo->bitmaps[id - 1].have_mask = 0;
dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
+ dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1);
dpyinfo->bitmaps[id - 1].depth = 1;
dpyinfo->bitmaps[id - 1].height = height;
dpyinfo->bitmaps[id - 1].width = width;
}
}
- xassert (interrupt_input_blocked);
+ eassert (interrupt_input_blocked);
gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
width, height);
{
/* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
The initialized data segment is read-only. */
- struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
+ struct image_type *p = xmalloc (sizeof *p);
memcpy (p, type, sizeof *p);
p->next = image_types;
image_types = p;
IMAGE_STRING_OR_NIL_VALUE,
IMAGE_SYMBOL_VALUE,
IMAGE_POSITIVE_INTEGER_VALUE,
- IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
+ IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR,
IMAGE_NON_NEGATIVE_INTEGER_VALUE,
IMAGE_ASCENT_VALUE,
IMAGE_INTEGER_VALUE,
/* Record that we recognized the keyword. If a keywords
was found more than once, it's an error. */
keywords[i].value = value;
- ++keywords[i].count;
-
if (keywords[i].count > 1)
return 0;
+ ++keywords[i].count;
/* Check type of value against allowed type. */
switch (keywords[i].type)
break;
case IMAGE_POSITIVE_INTEGER_VALUE:
- if (!INTEGERP (value) || XINT (value) <= 0)
+ if (! RANGED_INTEGERP (1, value, INT_MAX))
return 0;
break;
- case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
- if (INTEGERP (value) && XINT (value) >= 0)
+ case IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR:
+ if (RANGED_INTEGERP (0, value, INT_MAX))
break;
if (CONSP (value)
- && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
- && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+ && RANGED_INTEGERP (0, XCAR (value), INT_MAX)
+ && RANGED_INTEGERP (0, XCDR (value), INT_MAX))
break;
return 0;
case IMAGE_ASCENT_VALUE:
if (SYMBOLP (value) && EQ (value, Qcenter))
break;
- else if (INTEGERP (value)
- && XINT (value) >= 0
- && XINT (value) <= 100)
+ else if (RANGED_INTEGERP (0, value, 100))
break;
return 0;
case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
+ /* Unlike the other integer-related cases, this one does not
+ verify that VALUE fits in 'int'. This is because callers
+ want EMACS_INT. */
if (!INTEGERP (value) || XINT (value) < 0)
return 0;
break;
break;
case IMAGE_INTEGER_VALUE:
- if (!INTEGERP (value))
+ if (! TYPE_RANGED_INTEGERP (int, value))
return 0;
break;
{
Lisp_Object tail;
- xassert (valid_image_p (spec));
+ eassert (valid_image_p (spec));
for (tail = XCDR (spec);
CONSP (tail) && CONSP (XCDR (tail));
if (valid_image_p (spec))
{
struct frame *f = check_x_frame (frame);
- int id = lookup_image (f, spec);
+ ptrdiff_t id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
int width = img->width + 2 * img->hmargin;
int height = img->height + 2 * img->vmargin;
if (valid_image_p (spec))
{
struct frame *f = check_x_frame (frame);
- int id = lookup_image (f, spec);
+ ptrdiff_t id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
if (img->mask)
mask = Qt;
if (valid_image_p (spec))
{
struct frame *f = check_x_frame (frame);
- int id = lookup_image (f, spec);
+ ptrdiff_t id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
ext = img->lisp_data;
}
static void free_image (struct frame *f, struct image *img);
-#define MAX_IMAGE_SIZE 6.0
+#define MAX_IMAGE_SIZE 10.0
/* Allocate and return a new image structure for image specification
SPEC. SPEC has a hash value of HASH. */
static struct image *
make_image (Lisp_Object spec, EMACS_UINT hash)
{
- struct image *img = (struct image *) xmalloc (sizeof *img);
+ struct image *img = xzalloc (sizeof *img);
Lisp_Object file = image_spec_value (spec, QCfile, NULL);
- xassert (valid_image_p (spec));
- memset (img, 0, sizeof *img);
+ eassert (valid_image_p (spec));
img->dependencies = NILP (file) ? Qnil : list1 (file);
img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
- xassert (img->type != NULL);
+ eassert (img->type != NULL);
img->spec = spec;
img->lisp_data = Qnil;
img->ascent = DEFAULT_IMAGE_ASCENT;
void
prepare_image_for_display (struct frame *f, struct image *img)
{
- EMACS_TIME t;
-
/* We're about to display IMG, so set its timestamp to `now'. */
- EMACS_GET_TIME (t);
- img->timestamp = EMACS_SECS (t);
+ EMACS_GET_TIME (img->timestamp);
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
because a typical font is `top-heavy' (due to the presence
uppercase letters), so the image placement should err towards
being top-heavy too. It also just generally looks better. */
- ascent = (height + FONT_BASE(face->font)
- - FONT_DESCENT(face->font) + 1) / 2;
+ ascent = (height + FONT_BASE (face->font)
+ - FONT_DESCENT (face->font) + 1) / 2;
#endif /* HAVE_NTGUI */
}
else
ascent = height / 2;
}
else
- ascent = (int) (height * img->ascent / 100.0);
+ ascent = height * (img->ascent / 100.0);
return ascent;
}
XColor color;
unsigned long result;
- xassert (STRINGP (color_name));
+ eassert (STRINGP (color_name));
if (x_defined_color (f, SSDATA (color_name), &color, 1)
&& img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors,
{
/* This isn't called frequently so we get away with simply
reallocating the color vector to the needed size, here. */
- ++img->ncolors;
- img->colors =
- (unsigned long *) xrealloc (img->colors,
- img->ncolors * sizeof *img->colors);
- img->colors[img->ncolors - 1] = color.pixel;
+ ptrdiff_t ncolors = img->ncolors + 1;
+ img->colors = xrealloc (img->colors, ncolors * sizeof *img->colors);
+ img->colors[ncolors - 1] = color.pixel;
+ img->ncolors = ncolors;
result = color.pixel;
}
else
struct image_cache *
make_image_cache (void)
{
- struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
+ struct image_cache *c = xzalloc (sizeof *c);
int size;
- memset (c, 0, sizeof *c);
- c->size = 50;
- c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
+ size = 50;
+ c->images = xmalloc (size * sizeof *c->images);
+ c->size = size;
size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
- c->buckets = (struct image **) xmalloc (size);
- memset (c->buckets, 0, size);
+ c->buckets = xzalloc (size);
return c;
}
struct image_cache *c = FRAME_IMAGE_CACHE (f);
if (c)
{
- int i;
+ ptrdiff_t i;
/* Cache should not be referenced by any frame when freed. */
- xassert (c->refcount == 0);
+ eassert (c->refcount == 0);
for (i = 0; i < c->used; ++i)
free_image (f, c->images[i]);
if (c)
{
- int i, nfreed = 0;
+ ptrdiff_t i, nfreed = 0;
/* Block input so that we won't be interrupted by a SIGIO
while being in an inconsistent state. */
else if (INTEGERP (Vimage_cache_eviction_delay))
{
/* Free cache based on timestamp. */
- EMACS_TIME t;
- time_t old;
- int delay, nimages = 0;
+ EMACS_TIME old, t;
+ double delay;
+ ptrdiff_t nimages = 0;
for (i = 0; i < c->used; ++i)
if (c->images[i])
/* If the number of cached images has grown unusually large,
decrease the cache eviction delay (Bug#6230). */
- delay = XFASTINT (Vimage_cache_eviction_delay);
+ delay = XINT (Vimage_cache_eviction_delay);
if (nimages > 40)
- delay = max (1, 1600 * delay / (nimages*nimages));
+ delay = 1600 * delay / nimages / nimages;
+ delay = max (delay, 1);
EMACS_GET_TIME (t);
- old = EMACS_SECS (t) - delay;
+ EMACS_SUB_TIME (old, t, EMACS_TIME_FROM_DOUBLE (delay));
for (i = 0; i < c->used; ++i)
{
struct image *img = c->images[i];
- if (img && img->timestamp < old)
+ if (img && EMACS_TIME_LT (img->timestamp, old))
{
free_image (f, img);
++nfreed;
/* Return the id of image with Lisp specification SPEC on frame F.
SPEC must be a valid Lisp image specification (see valid_image_p). */
-int
+ptrdiff_t
lookup_image (struct frame *f, Lisp_Object spec)
{
struct image *img;
EMACS_UINT hash;
- EMACS_TIME now;
/* F must be a window-system frame, and SPEC must be a valid image
specification. */
- xassert (FRAME_WINDOW_P (f));
- xassert (valid_image_p (spec));
+ eassert (FRAME_WINDOW_P (f));
+ eassert (valid_image_p (spec));
/* Look up SPEC in the hash table of the image cache. */
hash = sxhash (spec, 0);
`:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
`:background COLOR'. */
Lisp_Object ascent, margin, relief, bg;
+ int relief_bound;
ascent = image_spec_value (spec, QCascent, NULL);
if (INTEGERP (ascent))
img->ascent = CENTERED_IMAGE_ASCENT;
margin = image_spec_value (spec, QCmargin, NULL);
- if (INTEGERP (margin) && XINT (margin) >= 0)
+ if (INTEGERP (margin))
img->vmargin = img->hmargin = XFASTINT (margin);
- else if (CONSP (margin) && INTEGERP (XCAR (margin))
- && INTEGERP (XCDR (margin)))
+ else if (CONSP (margin))
{
- if (XINT (XCAR (margin)) > 0)
- img->hmargin = XFASTINT (XCAR (margin));
- if (XINT (XCDR (margin)) > 0)
- img->vmargin = XFASTINT (XCDR (margin));
+ img->hmargin = XFASTINT (XCAR (margin));
+ img->vmargin = XFASTINT (XCDR (margin));
}
relief = image_spec_value (spec, QCrelief, NULL);
- if (INTEGERP (relief))
+ relief_bound = INT_MAX - max (img->hmargin, img->vmargin);
+ if (RANGED_INTEGERP (- relief_bound, relief, relief_bound))
{
img->relief = XINT (relief);
img->hmargin += eabs (img->relief);
}
/* We're using IMG, so set its timestamp to `now'. */
- EMACS_GET_TIME (now);
- img->timestamp = EMACS_SECS (now);
+ EMACS_GET_TIME (img->timestamp);
/* Value is the image id. */
return img->id;
cache_image (struct frame *f, struct image *img)
{
struct image_cache *c = FRAME_IMAGE_CACHE (f);
- int i;
+ ptrdiff_t i;
/* Find a free slot in c->images. */
for (i = 0; i < c->used; ++i)
/* If no free slot found, maybe enlarge c->images. */
if (i == c->used && c->used == c->size)
- {
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size)
- memory_full (SIZE_MAX);
- c->size *= 2;
- c->images = (struct image **) xrealloc (c->images,
- c->size * sizeof *c->images);
- }
+ c->images = xpalloc (c->images, &c->size, 1, -1, sizeof *c->images);
/* Add IMG to c->images, and assign IMG an id. */
c->images[i] = img;
{
if (c)
{
- int i;
+ ptrdiff_t i;
for (i = 0; i < c->used; ++i)
if (c->images[i])
mark_image (c->images[i]);
Window window = FRAME_X_WINDOW (f);
Screen *screen = FRAME_X_SCREEN (f);
- xassert (interrupt_input_blocked);
+ eassert (interrupt_input_blocked);
if (depth <= 0)
depth = DefaultDepthOfScreen (screen);
}
/* Allocate image raster. */
- (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
+ (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
/* Allocate a pixmap of the same size. */
*pixmap = XCreatePixmap (display, window, width, height, depth);
/* Bitmaps with a depth less than 16 need a palette. */
/* BITMAPINFO structure already contains the first RGBQUAD. */
if (depth < 16)
- palette_colors = 1 << depth - 1;
+ palette_colors = 1 << (depth - 1);
*ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
DWORD err = GetLastError ();
Lisp_Object errcode;
/* All system errors are < 10000, so the following is safe. */
- XSETINT (errcode, (int) err);
+ XSETINT (errcode, err);
image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
x_destroy_x_image (*ximg);
return 0;
static void
x_destroy_x_image (XImagePtr ximg)
{
- xassert (interrupt_input_blocked);
+ eassert (interrupt_input_blocked);
if (ximg)
{
#ifdef HAVE_X_WINDOWS
#ifdef HAVE_X_WINDOWS
GC gc;
- xassert (interrupt_input_blocked);
+ eassert (interrupt_input_blocked);
gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
XFreeGC (FRAME_X_DISPLAY (f), gc);
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
- xassert (ximg == pixmap);
+ eassert (ximg == pixmap);
ns_retain_object (ximg);
#endif
}
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),
+ && (buf = xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
*size = st.st_size;
{":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
{":background", IMAGE_STRING_OR_NIL_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
return 0;
- xassert (EQ (kw[XBM_TYPE].value, Qxbm));
+ eassert (EQ (kw[XBM_TYPE].value, Qxbm));
if (kw[XBM_FILE].count)
{
else
{
Lisp_Object data;
- EMACS_INT width, height;
+ int width, height;
/* Entries for `:width', `:height' and `:data' must be present. */
if (!kw[XBM_WIDTH].count
for one line of the image. */
for (i = 0; i < height; ++i)
{
- Lisp_Object elt = XVECTOR (data)->contents[i];
+ Lisp_Object elt = AREF (data, i);
if (STRINGP (elt))
{
w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
- bits = (unsigned char *) alloca (height * w2);
+ bits = alloca (height * w2);
memset (bits, 0, height * w2);
for (i = 0; i < height; i++)
{
}
bytes_per_line = (*width + 7) / 8 + padding_p;
nbytes = bytes_per_line * *height;
- p = *data = (char *) xmalloc (nbytes);
+ p = *data = xmalloc (nbytes);
if (v10)
{
int non_default_colors = 0;
Lisp_Object value;
- xassert (img->width > 0 && img->height > 0);
+ eassert (img->width > 0 && img->height > 0);
/* Get foreground and background colors, maybe allocate colors. */
value = image_spec_value (img->spec, QCforeground, NULL);
int success_p = 0;
Lisp_Object file_name;
- xassert (xbm_image_p (img->spec));
+ eassert (xbm_image_p (img->spec));
/* If IMG->spec specifies a file name, create a non-file spec from it. */
file_name = image_spec_value (img->spec, QCfile, NULL);
memcpy (fmt, xbm_format, sizeof fmt);
parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
(void) parsed_p;
- xassert (parsed_p);
+ eassert (parsed_p);
/* Get specified width, and height. */
if (!in_memory_file_p)
{
img->width = XFASTINT (fmt[XBM_WIDTH].value);
img->height = XFASTINT (fmt[XBM_HEIGHT].value);
- xassert (img->width > 0 && img->height > 0);
+ eassert (img->width > 0 && img->height > 0);
if (!check_image_size (f, img->width, img->height))
{
image_error ("Invalid image size (see `max-image-size')",
char *p;
int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
- p = bits = (char *) alloca (nbytes * img->height);
+ p = bits = alloca (nbytes * img->height);
for (i = 0; i < img->height; ++i, p += nbytes)
{
- Lisp_Object line = XVECTOR (data)->contents[i];
+ Lisp_Object line = AREF (data, i);
if (STRINGP (line))
memcpy (p, SDATA (line), nbytes);
else
invertedBits = bits;
nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
* img->height;
- bits = (char *) alloca (nbytes);
+ bits = alloca (nbytes);
for (i = 0; i < nbytes; i++)
bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
}
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
{
size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
- xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
- memset (xpm_color_cache, 0, nbytes);
+ xpm_color_cache = xzalloc (nbytes);
init_color_table ();
if (attrs->valuemask & XpmColorSymbols)
bucket = xpm_color_bucket (color_name);
nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1;
- p = (struct xpm_cached_color *) xmalloc (nbytes);
+ p = xmalloc (nbytes);
strcpy (p->name, color_name);
p->color = *color;
p->next = xpm_color_cache[bucket];
/* Allocate an XpmColorSymbol array. */
size = attrs.numsymbols * sizeof *xpm_syms;
- xpm_syms = (XpmColorSymbol *) alloca (size);
+ xpm_syms = alloca (size);
memset (xpm_syms, 0, size);
attrs.colorsymbols = xpm_syms;
color = XCDR (XCAR (tail));
if (STRINGP (name))
{
- xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
+ xpm_syms[i].name = alloca (SCHARS (name) + 1);
strcpy (xpm_syms[i].name, SSDATA (name));
}
else
xpm_syms[i].name = empty_string;
if (STRINGP (color))
{
- xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
+ xpm_syms[i].value = alloca (SCHARS (color) + 1);
strcpy (xpm_syms[i].value, SSDATA (color));
}
else
#endif /* HAVE_NTGUI */
/* Remember allocated colors. */
+ img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors);
img->ncolors = attrs.nalloc_pixels;
- img->colors = (unsigned long *) xmalloc (img->ncolors
- * sizeof *img->colors);
for (i = 0; i < attrs.nalloc_pixels; ++i)
{
img->colors[i] = attrs.alloc_pixels[i];
img->width = attrs.width;
img->height = attrs.height;
- xassert (img->width > 0 && img->height > 0);
+ eassert (img->width > 0 && img->height > 0);
/* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
#ifdef HAVE_NTGUI
int chars_len,
Lisp_Object color)
{
- XVECTOR (color_table)->contents[*chars_start] = color;
+ ASET (color_table, *chars_start, color);
}
static Lisp_Object
const unsigned char *chars_start,
int chars_len)
{
- return XVECTOR (color_table)->contents[*chars_start];
+ return AREF (color_table, *chars_start);
}
static Lisp_Object
int chars_len)
{
struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
- int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
- NULL);
+ ptrdiff_t i =
+ hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
return i >= 0 ? HASH_VALUE (table, i) : Qnil;
}
/* Number of entries in the color table. */
static int ct_colors_allocated;
+enum
+{
+ ct_colors_allocated_max =
+ min (INT_MAX,
+ min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long))
+};
/* Initialize the color table. */
init_color_table (void)
{
int size = CT_SIZE * sizeof (*ct_table);
- ct_table = (struct ct_color **) xmalloc (size);
- memset (ct_table, 0, size);
+ ct_table = xzalloc (size);
ct_colors_allocated = 0;
}
XColor color;
Colormap cmap;
int rc;
+#else
+ COLORREF color;
+#endif
+
+ if (ct_colors_allocated_max <= ct_colors_allocated)
+ return FRAME_FOREGROUND_PIXEL (f);
+#ifdef HAVE_X_WINDOWS
color.red = r;
color.green = g;
color.blue = b;
if (rc)
{
++ct_colors_allocated;
- p = (struct ct_color *) xmalloc (sizeof *p);
+ p = xmalloc (sizeof *p);
p->r = r;
p->g = g;
p->b = b;
return FRAME_FOREGROUND_PIXEL (f);
#else
- COLORREF color;
#ifdef HAVE_NTGUI
color = PALETTERGB (r, g, b);
#else
color = RGB_TO_ULONG (r, g, b);
#endif /* HAVE_NTGUI */
++ct_colors_allocated;
- p = (struct ct_color *) xmalloc (sizeof *p);
+ p = xmalloc (sizeof *p);
p->r = r;
p->g = g;
p->b = b;
Colormap cmap;
int rc;
+ if (ct_colors_allocated_max <= ct_colors_allocated)
+ return FRAME_FOREGROUND_PIXEL (f);
+
#ifdef HAVE_X_WINDOWS
cmap = FRAME_X_COLORMAP (f);
color.pixel = pixel;
{
++ct_colors_allocated;
- p = (struct ct_color *) xmalloc (sizeof *p);
+ p = xmalloc (sizeof *p);
p->r = color.red;
p->g = color.green;
p->b = color.blue;
}
else
{
- colors = (unsigned long *) xmalloc (ct_colors_allocated
- * sizeof *colors);
+ colors = xmalloc (ct_colors_allocated * sizeof *colors);
*n = ct_colors_allocated;
for (i = j = 0; i < CT_SIZE; ++i)
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
- colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+ if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+ memory_full (SIZE_MAX);
+ colors = xmalloc (sizeof *colors * img->width * img->height);
#ifndef HAVE_NTGUI
/* Get the X image IMG->pixmap. */
#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
- new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+ if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+ memory_full (SIZE_MAX);
+ new = xmalloc (sizeof *new * img->width * img->height);
for (y = 0; y < img->height; ++y)
{
#else
/* Create the bit array serving as mask. */
row_width = (img->width + 7) / 8;
- mask_img = xmalloc (row_width * img->height);
- memset (mask_img, 0, row_width * img->height);
+ mask_img = xzalloc (row_width * img->height);
/* Create a memory device context for IMG->pixmap. */
frame_dc = get_frame_dc (f);
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
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),
+ && (buf = xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
*size = st.st_size;
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
/* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */
#define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
#define PNG_JMPBUF(ptr) \
- (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf)))
+ (*fn_png_set_longjmp_fn ((ptr), longjmp, sizeof (jmp_buf)))
#endif
/* Error and warning handlers installed when the PNG library
is initialized. */
-static void my_png_error (png_struct *, const char *) NO_RETURN;
-static void
+static _Noreturn void
my_png_error (png_struct *png_ptr, const char *msg)
{
- xassert (png_ptr != NULL);
+ eassert (png_ptr != NULL);
/* Avoid compiler warning about deprecated direct access to
png_ptr's fields in libpng versions 1.4.x. */
image_error ("PNG error: %s", build_string (msg), Qnil);
static void
my_png_warning (png_struct *png_ptr, const char *msg)
{
- xassert (png_ptr != NULL);
+ eassert (png_ptr != NULL);
image_error ("PNG warning: %s", build_string (msg), Qnil);
}
images with alpha channel, i.e. RGBA. If conversions above were
sufficient we should only have 3 or 4 channels here. */
channels = fn_png_get_channels (png_ptr, info_ptr);
- xassert (channels == 3 || channels == 4);
+ eassert (channels == 3 || channels == 4);
/* Number of bytes needed for one row of the image. */
row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
|| min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
memory_full (SIZE_MAX);
- pixels = (png_byte *) xmalloc (sizeof *pixels * row_bytes * height);
- rows = (png_byte **) xmalloc (height * sizeof *rows);
+ pixels = xmalloc (sizeof *pixels * row_bytes * height);
+ rows = xmalloc (height * sizeof *rows);
for (i = 0; i < height; ++i)
rows[i] = pixels + i * row_bytes;
for (x = 0; x < width; ++x)
{
- unsigned r, g, b;
+ int r, g, b;
r = *p++ << 8;
g = *p++ << 8;
static int
png_load (struct frame *f, struct image *img)
{
- return ns_load_image(f, img,
- image_spec_value (img->spec, QCfile, NULL),
- image_spec_value (img->spec, QCdata, NULL));
+ return ns_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
}
#endif /* HAVE_NS */
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
#else
-#define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
+#define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress (a)
#define fn_jpeg_start_decompress jpeg_start_decompress
#define fn_jpeg_finish_decompress jpeg_finish_decompress
#define fn_jpeg_destroy_decompress jpeg_destroy_decompress
};
-static void my_error_exit (j_common_ptr) NO_RETURN;
-static void
+static _Noreturn void
my_error_exit (j_common_ptr cinfo)
{
struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
a default color, and we don't have to care about which colors
can be freed safely, and which can't. */
init_color_table ();
- colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
- * sizeof *colors);
+ colors = alloca (cinfo.actual_number_of_colors * sizeof *colors);
for (i = 0; i < cinfo.actual_number_of_colors; ++i)
{
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
return ((tiff_memory_source *) data)->len;
}
+/* GCC 3.x on x86 Windows targets has a bug that triggers an internal
+ compiler error compiling tiff_handler, see Bugzilla bug #17406
+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring
+ this function as external works around that problem. */
+#if defined (__MINGW32__) && __GNUC__ == 3
+# define MINGW_STATIC
+#else
+# define MINGW_STATIC static
+#endif
+
+MINGW_STATIC void
+tiff_handler (const char *, const char *, const char *, va_list)
+ ATTRIBUTE_FORMAT_PRINTF (3, 0);
+MINGW_STATIC void
+tiff_handler (const char *log_format, const char *title,
+ const char *format, va_list ap)
+{
+ /* doprnt is not suitable here, as TIFF handlers are called from
+ libtiff and are passed arbitrary printf directives. Instead, use
+ vsnprintf, taking care to be portable to nonstandard environments
+ where vsnprintf returns -1 on buffer overflow. Since it's just a
+ log entry, it's OK to truncate it. */
+ char buf[4000];
+ int len = vsnprintf (buf, sizeof buf, format, ap);
+ add_to_log (log_format, build_string (title),
+ make_string (buf, max (0, min (len, sizeof buf - 1))));
+}
+#undef MINGW_STATIC
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)
{
- char buf[512];
- int len;
-
- len = sprintf (buf, "TIFF error: %s ", title);
- vsprintf (buf + len, format, ap);
- add_to_log (buf, Qnil, Qnil);
+ tiff_handler ("TIFF error: %s %s", title, format, ap);
}
static void
tiff_warning_handler (const char *title, const char *format, va_list ap)
{
- char buf[512];
- int len;
-
- len = sprintf (buf, "TIFF warning: %s ", title);
- vsprintf (buf + len, format, ap);
- add_to_log (buf, Qnil, Qnil);
+ tiff_handler ("TIFF warning: %s %s", title, format, ap);
}
image = image_spec_value (img->spec, QCindex, NULL);
if (INTEGERP (image))
{
- int ino = XFASTINT (image);
- if (!fn_TIFFSetDirectory (tiff, ino))
+ EMACS_INT ino = XFASTINT (image);
+ if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
+ && fn_TIFFSetDirectory (tiff, ino)))
{
image_error ("Invalid image number `%s' in image `%s'",
image, img->spec);
return 0;
}
- buf = (uint32 *) xmalloc (sizeof *buf * width * height);
+ buf = xmalloc (sizeof *buf * width * height);
rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
ColorMapObject *gif_color_map;
unsigned long pixel_colors[256];
GifFileType *gif;
- int image_height, image_width;
gif_memory_source memsrc;
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;
+ EMACS_INT idx;
if (NILP (specified_data))
{
}
}
- 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[idx].ImageDesc.Width;
- img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
+ width = img->width = gif->SWidth;
+ height = img->height = gif->SHeight;
- width = img->width = max (gif->SWidth,
- max (gif->Image.Left + gif->Image.Width,
- img->corners[RIGHT_CORNER]));
- height = img->height = max (gif->SHeight,
- max (gif->Image.Top + gif->Image.Height,
- img->corners[BOT_CORNER]));
+ img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
+ img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
+ img->corners[BOT_CORNER]
+ = img->corners[TOP_CORNER] + gif->SavedImages[0].ImageDesc.Height;
+ img->corners[RIGHT_CORNER]
+ = img->corners[LEFT_CORNER] + gif->SavedImages[0].ImageDesc.Width;
if (!check_image_size (f, width, height))
{
unsigned char *raster = (unsigned char *) subimage->RasterBits;
int transparency_color_index = -1;
int disposal = 0;
+ int subimg_width = subimage->ImageDesc.Width;
+ int subimg_height = subimage->ImageDesc.Height;
+ int subimg_top = subimage->ImageDesc.Top;
+ int subimg_left = subimage->ImageDesc.Left;
/* Find the Graphic Control Extension block for this sub-image.
Extract the disposal method and transparency color. */
if (j == 0)
disposal = 2;
+ /* For disposal == 0, the spec says "No disposal specified. The
+ decoder is not required to take any action." In practice, it
+ seems we need to treat this like "keep in place", see e.g.
+ http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */
+ if (disposal == 0)
+ disposal = 1;
+
/* Allocate subimage colors. */
memset (pixel_colors, 0, sizeof pixel_colors);
gif_color_map = subimage->ImageDesc.ColorMap;
int row, pass;
for (y = 0, row = interlace_start[0], pass = 0;
- y < image_height;
+ y < subimg_height;
y++, row += interlace_increment[pass])
{
- if (row >= image_height)
+ if (row >= subimg_height)
{
row = interlace_start[++pass];
- while (row >= image_height)
+ while (row >= subimg_height)
row = interlace_start[++pass];
}
- for (x = 0; x < image_width; x++)
+ for (x = 0; x < subimg_width; x++)
{
- int c = raster[y * image_width + x];
+ int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
- XPutPixel (ximg, x + img->corners[LEFT_CORNER],
- row + img->corners[TOP_CORNER], pixel_colors[c]);
+ XPutPixel (ximg, x + subimg_left, row + subimg_top,
+ pixel_colors[c]);
}
}
}
else
{
- for (y = 0; y < image_height; ++y)
- for (x = 0; x < image_width; ++x)
+ for (y = 0; y < subimg_height; ++y)
+ for (x = 0; x < subimg_width; ++x)
{
- int c = raster[y * image_width + x];
+ int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
- XPutPixel (ximg, x + img->corners[LEFT_CORNER],
- y + img->corners[TOP_CORNER], pixel_colors[c]);
+ XPutPixel (ximg, x + subimg_left, y + subimg_top,
+ pixel_colors[c]);
}
}
}
img->lisp_data = Qnil;
if (gif->SavedImages[idx].ExtensionBlockCount > 0)
{
- unsigned int delay = 0;
+ int delay = 0;
ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
/* Append (... FUNCTION "BYTES") */
if (delay)
img->lisp_data
= Fcons (Qdelay,
- Fcons (make_float (((double) delay) * 0.01),
+ Fcons (make_float (delay / 100.0),
img->lisp_data));
}
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
}
/* The GIF library also defines DrawRectangle, but its never used in Emacs.
- Therefore rename the function so it doesnt collide with ImageMagick. */
+ Therefore rename the function so it doesn't collide with ImageMagick. */
#define DrawRectangle DrawRectangleGif
#include <wand/MagickWand.h>
MagickPixelPacket *);
#endif
+/* Log ImageMagick error message.
+ Useful when a ImageMagick function returns the status `MagickFalse'. */
+
+static void
+imagemagick_error (MagickWand *wand)
+{
+ char *description;
+ ExceptionType severity;
+
+ description = MagickGetException (wand, &severity);
+ image_error ("ImageMagick error: %s",
+ build_string (description),
+ Qnil);
+ description = (char *) MagickRelinquishMemory (description);
+}
+
/* 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
unsigned char *contents, unsigned int size,
char *filename)
{
- size_t width;
- size_t height;
-
+ size_t width, height;
MagickBooleanType status;
-
XImagePtr ximg;
- int x;
- int y;
-
- MagickWand *image_wand;
- MagickWand *ping_wand;
+ int x, y;
+ MagickWand *image_wand;
+ MagickWand *ping_wand;
PixelIterator *iterator;
- PixelWand **pixels;
+ PixelWand **pixels, *bg_wand = NULL;
MagickPixelPacket pixel;
Lisp_Object image;
Lisp_Object value;
Lisp_Object crop;
- long ino;
+ EMACS_INT ino;
int desired_width, desired_height;
double rotation;
- int imagemagick_rendermethod;
int pixelwidth;
- ImageInfo *image_info;
- ExceptionInfo *exception;
- 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
image = image_spec_value (img->spec, QCindex, NULL);
ino = INTEGERP (image) ? XFASTINT (image) : 0;
ping_wand = NewMagickWand ();
- MagickSetResolution (ping_wand, 2, 2);
- if (filename != NULL)
- {
- status = MagickPingImage (ping_wand, filename);
- }
- else
+ /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */
+
+ status = filename
+ ? MagickPingImage (ping_wand, filename)
+ : MagickPingImageBlob (ping_wand, contents, size);
+
+ if (status == MagickFalse)
{
- status = MagickPingImageBlob (ping_wand, contents, size);
+ imagemagick_error (ping_wand);
+ DestroyMagickWand (ping_wand);
+ return 0;
}
- if (ino >= MagickGetNumberImages (ping_wand))
+ if (ino < 0 || ino >= MagickGetNumberImages (ping_wand))
{
image_error ("Invalid image number `%s' in image `%s'",
image, img->spec);
return 0;
}
- if (MagickGetNumberImages(ping_wand) > 1)
+ if (MagickGetNumberImages (ping_wand) > 1)
img->lisp_data =
Fcons (Qcount,
Fcons (make_number (MagickGetNumberImages (ping_wand)),
DestroyMagickWand (ping_wand);
/* Now we know how many images are inside the file. If it's not a
- bundle, the number is one. */
+ bundle, the number is one. Load the image data. */
- if (filename != NULL)
- {
- image_info = CloneImageInfo ((ImageInfo *) NULL);
- (void) strcpy (image_info->filename, filename);
- image_info->number_scenes = 1;
- image_info->scene = ino;
- exception = AcquireExceptionInfo ();
-
- im_image = ReadImage (image_info, exception);
- DestroyExceptionInfo (exception);
+ image_wand = NewMagickWand ();
- if (im_image == NULL)
- goto imagemagick_no_wand;
- image_wand = NewMagickWandFromImage (im_image);
- DestroyImage(im_image);
- }
- else
+ if ((filename
+ ? MagickReadImage (image_wand, filename)
+ : MagickReadImageBlob (image_wand, contents, size))
+ == MagickFalse)
{
- image_wand = NewMagickWand ();
- if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
- goto imagemagick_error;
+ imagemagick_error (image_wand);
+ goto imagemagick_error;
}
+ /* Retrieve the frame's background color, for use later. */
+ {
+ XColor bgcolor;
+ Lisp_Object specified_bg;
+
+ specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+ if (!STRINGP (specified_bg)
+ || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0))
+ {
+#ifndef HAVE_NS
+ bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f);
+ x_query_color (f, &bgcolor);
+#else
+ ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1);
+#endif
+ }
+
+ bg_wand = NewPixelWand ();
+ PixelSetRed (bg_wand, (double) bgcolor.red / 65535);
+ PixelSetGreen (bg_wand, (double) bgcolor.green / 65535);
+ PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535);
+ }
+
/* 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
unspecified should be calculated from the specified to preserve
aspect ratio. */
-
value = image_spec_value (img->spec, QCwidth, NULL);
desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
value = image_spec_value (img->spec, QCheight, NULL);
if (status == MagickFalse)
{
image_error ("Imagemagick scale failed", Qnil, Qnil);
+ imagemagick_error (image_wand);
goto imagemagick_error;
}
}
efficient. */
crop = image_spec_value (img->spec, QCcrop, NULL);
- if (CONSP (crop) && INTEGERP (XCAR (crop)))
+ if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, 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
+ before cropping, which is apparently difficult to avoid when using
imagemagick. */
- int w, h;
- w = XFASTINT (XCAR (crop));
+ size_t crop_width = XINT (XCAR (crop));
crop = XCDR (crop);
- if (CONSP (crop) && INTEGERP (XCAR (crop)))
+ if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
{
- h = XFASTINT (XCAR (crop));
+ size_t crop_height = XINT (XCAR (crop));
crop = XCDR (crop);
- if (CONSP (crop) && INTEGERP (XCAR (crop)))
+ if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
{
- x = XFASTINT (XCAR (crop));
+ ssize_t crop_x = XINT (XCAR (crop));
crop = XCDR (crop);
- if (CONSP (crop) && INTEGERP (XCAR (crop)))
+ if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
{
- y = XFASTINT (XCAR (crop));
- MagickCropImage (image_wand, w, h, x, y);
+ ssize_t crop_y = XINT (XCAR (crop));
+ MagickCropImage (image_wand, crop_width, crop_height,
+ crop_x, crop_y);
}
}
}
value = image_spec_value (img->spec, QCrotation, NULL);
if (FLOATP (value))
{
- PixelWand* background = NewPixelWand ();
- PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/
-
rotation = extract_float (value);
-
- status = MagickRotateImage (image_wand, background, rotation);
- DestroyPixelWand (background);
+ status = MagickRotateImage (image_wand, bg_wand, rotation);
if (status == MagickFalse)
{
image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+ imagemagick_error (image_wand);
goto imagemagick_error;
}
}
/* Finally we are done manipulating the image. Figure out the
- resulting width/height and transfer ownerwship to Emacs. */
+ resulting width/height and transfer ownership to Emacs. */
height = MagickGetImageHeight (image_wand);
width = MagickGetImageWidth (image_wand);
+ /* Set the canvas background color to the frame or specified
+ background, and flatten the image. Note: as of ImageMagick
+ 6.6.0, SVG image transparency is not handled properly
+ (e.g. etc/images/splash.svg shows a white background always). */
+ {
+ MagickWand *new_wand;
+ MagickSetImageBackgroundColor (image_wand, bg_wand);
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+ new_wand = MagickMergeImageLayers (image_wand, MergeLayer);
+#else
+ new_wand = MagickFlattenImages (image_wand);
+#endif
+ DestroyMagickWand (image_wand);
+ image_wand = new_wand;
+ }
+
if (! (width <= INT_MAX && height <= INT_MAX
&& check_image_size (f, width, height)))
{
went ok. */
init_color_table ();
- imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type)
- ? XFASTINT (Vimagemagick_render_type) : 0);
- if (imagemagick_rendermethod == 0)
+
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+ if (imagemagick_render_type != 0)
+ {
+ /* Magicexportimage is normally faster than pixelpushing. This
+ 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);*/
+ 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))
+ {
+#ifdef COLOR_TABLE_SUPPORT
+ free_color_table ();
+#endif
+ image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+ /* Oddly, the below code doesn't seem to work:*/
+ /* switch(ximg->bitmap_unit){ */
+ /* case 8: */
+ /* pixelwidth=CharPixel; */
+ /* break; */
+ /* case 16: */
+ /* pixelwidth=ShortPixel; */
+ /* break; */
+ /* case 32: */
+ /* pixelwidth=LongPixel; */
+ /* break; */
+ /* } */
+ /*
+ Here im just guessing the format of the bitmap.
+ happens to work fine for:
+ - bw djvu images
+ on rgb display.
+ seems about 3 times as fast as pixel pushing(not carefully measured)
+ */
+ pixelwidth = CharPixel; /*??? TODO figure out*/
+ MagickExportImagePixels (image_wand, 0, 0, width, height,
+ exportdepth, pixelwidth, ximg->data);
+ }
+ else
+#endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */
{
+ size_t image_height;
+
/* Try to create a x pixmap to hold the imagemagick pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0,
&ximg, &img->pixmap))
#ifdef COLOR_TABLE_SUPPORT
free_color_table ();
#endif
- image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
goto imagemagick_error;
}
- /* Copy imagegmagick image to x with primitive yet robust pixel
+ /* Copy imagemagick image to x with primitive yet robust pixel
pusher loop. This has been tested a lot with many different
images. */
goto imagemagick_error;
}
- for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++)
+ image_height = MagickGetImageHeight (image_wand);
+ for (y = 0; y < image_height; y++)
{
pixels = PixelGetNextIteratorRow (iterator, &width);
if (pixels == (PixelWand **) NULL)
DestroyPixelIterator (iterator);
}
- if (imagemagick_rendermethod == 1)
- {
- /* Magicexportimage is normaly faster than pixelpushing. This
- 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);*/
- 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))
- {
-#ifdef COLOR_TABLE_SUPPORT
- free_color_table ();
-#endif
- image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
- goto imagemagick_error;
- }
-
-
- /* Oddly, the below code doesnt seem to work:*/
- /* switch(ximg->bitmap_unit){ */
- /* case 8: */
- /* pixelwidth=CharPixel; */
- /* break; */
- /* case 16: */
- /* pixelwidth=ShortPixel; */
- /* break; */
- /* case 32: */
- /* pixelwidth=LongPixel; */
- /* break; */
- /* } */
- /*
- Here im just guessing the format of the bitmap.
- happens to work fine for:
- - bw djvu images
- on rgb display.
- seems about 3 times as fast as pixel pushing(not carefully measured)
- */
- pixelwidth = CharPixel;/*??? TODO figure out*/
-#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
- MagickExportImagePixels (image_wand,
- 0, 0,
- width, height,
- exportdepth,
- pixelwidth,
- /*&(img->pixmap));*/
- ximg->data);
-#else
- image_error ("You dont have MagickExportImagePixels, upgrade ImageMagick!",
- Qnil, Qnil);
-#endif
- }
-
-
#ifdef COLOR_TABLE_SUPPORT
/* Remember colors allocated for this image. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
#endif /* COLOR_TABLE_SUPPORT */
-
img->width = width;
img->height = height;
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
-
/* Final cleanup. image_wand should be the only resource left. */
DestroyMagickWand (image_wand);
+ if (bg_wand) DestroyPixelWand (bg_wand);
+
/* `MagickWandTerminus' terminates the imagemagick environment. */
MagickWandTerminus ();
imagemagick_error:
DestroyMagickWand (image_wand);
- imagemagick_no_wand:
+ if (bg_wand) DestroyPixelWand (bg_wand);
+
MagickWandTerminus ();
/* TODO more cleanup. */
image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
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).
+You can also try the shell command: `identify -list format'.
Note that ImageMagick recognizes many file-types that Emacs does not
-recognize as images, such as C. See `imagemagick-types-inhibit'. */)
+recognize as images, such as C. See `imagemagick-types-enable'
+and `imagemagick-types-inhibit'. */)
(void)
{
Lisp_Object typelist = Qnil;
Qimagemagicktype = intern (imtypes[i]);
typelist = Fcons (Qimagemagicktype, typelist);
}
- return typelist;
+ return Fnreverse (typelist);
}
#endif /* defined (HAVE_IMAGEMAGICK) */
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{
for (x = 0; x < width; ++x)
{
- unsigned red;
- unsigned green;
- unsigned blue;
- unsigned opacity;
+ int red;
+ int green;
+ int blue;
+ int opacity;
red = *pixels++;
green = *pixels++;
{":loader", IMAGE_FUNCTION_VALUE, 0},
{":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
if (ASIZE (tem) != 4)
return 0;
for (i = 0; i < 4; ++i)
- if (!INTEGERP (XVECTOR (tem)->contents[i]))
+ if (!INTEGERP (AREF (tem, i)))
return 0;
}
else
static int
gs_load (struct frame *f, struct image *img)
{
- char buffer[100];
+ uprintmax_t printnum1, printnum2;
+ char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
Lisp_Object frame;
double in_width, in_height;
info. */
pt_width = image_spec_value (img->spec, QCpt_width, NULL);
in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
- img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
+ in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
pt_height = image_spec_value (img->spec, QCpt_height, NULL);
in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
- img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
+ in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
- if (!check_image_size (f, img->width, img->height))
+ if (! (in_width <= INT_MAX && in_height <= INT_MAX
+ && check_image_size (f, in_width, in_height)))
{
image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
return 0;
}
+ img->width = in_width;
+ img->height = in_height;
/* Create the pixmap. */
- xassert (img->pixmap == NO_PIXMAP);
+ eassert (img->pixmap == NO_PIXMAP);
if (x_check_image_size (0, img->width, img->height))
{
if successful. We do not record_unwind_protect here because
other places in redisplay like calling window scroll functions
don't either. Let the Lisp loader use `unwind-protect' instead. */
- sprintf (buffer, "%lu %lu",
- (unsigned long) FRAME_X_WINDOW (f),
- (unsigned long) img->pixmap);
+ printnum1 = FRAME_X_WINDOW (f);
+ printnum2 = img->pixmap;
+ sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
window_and_pixmap_id = build_string (buffer);
- sprintf (buffer, "%lu %lu",
- FRAME_FOREGROUND_PIXEL (f),
- FRAME_BACKGROUND_PIXEL (f));
+ printnum1 = FRAME_FOREGROUND_PIXEL (f);
+ printnum2 = FRAME_BACKGROUND_PIXEL (f);
+ sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
pixel_colors = build_string (buffer);
XSETFRAME (frame, f);
x_kill_gs_process (Pixmap pixmap, struct frame *f)
{
struct image_cache *c = FRAME_IMAGE_CACHE (f);
- int class, i;
+ int class;
+ ptrdiff_t i;
struct image *img;
/* Find the image containing PIXMAP. */
/* Kill the GS process. We should have found PIXMAP in the image
cache and its image should contain a process object. */
img = c->images[i];
- xassert (PROCESSP (img->lisp_data));
+ eassert (PROCESSP (img->lisp_data));
Fkill_process (img->lisp_data, Qnil);
img->lisp_data = Qnil;
Tests
***********************************************************************/
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
doc: /* Value is non-nil if SPEC is a valid image specification. */)
DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
(Lisp_Object spec)
{
- int id = -1;
+ ptrdiff_t id = -1;
if (valid_image_p (spec))
id = lookup_image (SELECTED_FRAME (), spec);
return make_number (id);
}
-#endif /* GLYPH_DEBUG != 0 */
+#endif /* GLYPH_DEBUG */
/***********************************************************************
operation on GNU/Linux of calling dump-emacs after loading some images. */
image_types = NULL;
- /* Must be defined now becase we're going to update it below, while
+ /* Must be defined now because we're going to update it below, while
defining the supported image types. */
DEFVAR_LISP ("image-types", Vimage_types,
doc: /* List of potentially supported image types.
defsubr (&Simage_mask_p);
defsubr (&Simage_metadata);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
defsubr (&Simagep);
defsubr (&Slookup_image);
#endif
The function `clear-image-cache' disregards this variable. */);
Vimage_cache_eviction_delay = make_number (300);
#ifdef HAVE_IMAGEMAGICK
- DEFVAR_LISP ("imagemagick-render-type", Vimagemagick_render_type,
- doc: /* Choose between ImageMagick render methods. */);
+ DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type,
+ doc: /* Integer indicating which ImageMagick rendering method to use.
+The options are:
+ 0 -- the default method (pixel pushing)
+ 1 -- a newer method ("MagickExportImagePixels") that may perform
+ better (speed etc) in some cases, but has not been as thoroughly
+ tested with Emacs as the default method. This method requires
+ ImageMagick version 6.4.6 (approximately) or later.
+*/);
+ /* MagickExportImagePixels is in 6.4.6-9, but not 6.4.4-10. */
+ imagemagick_render_type = 0;
#endif
}