/* Functions for image support on window system.
- Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
+
+Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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
}
}
- 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);
{
Lisp_Object tail;
- xassert (valid_image_p (spec));
+ eassert (valid_image_p (spec));
for (tail = XCDR (spec);
CONSP (tail) && CONSP (XCDR (tail));
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. */
struct image *img = (struct image *) xmalloc (sizeof *img);
Lisp_Object file = image_spec_value (spec, QCfile, NULL);
- xassert (valid_image_p (spec));
+ eassert (valid_image_p (spec));
memset (img, 0, sizeof *img);
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. */
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,
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]);
else if (INTEGERP (Vimage_cache_eviction_delay))
{
/* Free cache based on timestamp. */
- EMACS_TIME t;
- double old, delay;
+ EMACS_TIME old, t;
+ double delay;
ptrdiff_t nimages = 0;
for (i = 0; i < c->used; ++i)
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;
{
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);
}
/* 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;
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);
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 (!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)
{
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))
{
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')",
p = bits = (char *) 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
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
/* 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);
};
-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;
description = MagickGetException (wand, &severity);
image_error ("ImageMagick error: %s",
- make_string (description, strlen (description)),
+ build_string (description),
Qnil);
description = (char *) MagickRelinquishMemory (description);
}
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;
int desired_width, desired_height;
double rotation;
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
ping_wand = NewMagickWand ();
/* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */
- if (filename != NULL)
- {
- status = MagickPingImage (ping_wand, filename);
- }
- else
- {
- status = MagickPingImageBlob (ping_wand, contents, size);
- }
+ status = filename
+ ? MagickPingImage (ping_wand, filename)
+ : MagickPingImageBlob (ping_wand, contents, size);
if (status == MagickFalse)
{
return 0;
}
- if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand)))
+ if (ino < 0 || ino >= MagickGetNumberImages (ping_wand))
{
image_error ("Invalid image number `%s' in image `%s'",
image, img->spec);
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)
- {
- imagemagick_error (image_wand);
- 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);
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);
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)))
{
init_color_table ();
- if (imagemagick_render_type == 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;
}
DestroyPixelIterator (iterator);
}
- else /* 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*/
-#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
- MagickExportImagePixels (image_wand,
- 0, 0,
- width, height,
- exportdepth,
- pixelwidth,
- /*&(img->pixmap));*/
- ximg->data);
-#else
- image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!",
- Qnil, Qnil);
-#endif
- }
-
#ifdef COLOR_TABLE_SUPPORT
/* Remember colors allocated for this image. */
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);
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;
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
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))
{
/* 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. */)
return make_number (id);
}
-#endif /* GLYPH_DEBUG != 0 */
+#endif /* GLYPH_DEBUG */
/***********************************************************************
defsubr (&Simage_mask_p);
defsubr (&Simage_metadata);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
defsubr (&Simagep);
defsubr (&Slookup_image);
#endif