/* Functions for image support on window system.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#include "blockinput.h"
#include "systime.h"
#include <epaths.h>
+#include "charset.h"
+#include "coding.h"
#ifdef HAVE_X_WINDOWS
#define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
#define x_defined_color mac_defined_color
#define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
-#define XDrawLine(display, w, gc, x1, y1, x2, y2) \
- mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
#endif /* MAC_OS */
PixMapHandle pixmap = GetGWorldPixMap (ximage);
short depth = GetPixDepth (pixmap);
+#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
if (depth == 32)
{
char *base_addr = GetPixBaseAddr (pixmap);
short row_bytes = GetPixRowBytes (pixmap);
- ((unsigned long *) (base_addr + y * row_bytes))[x] = pixel;
+ ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
}
- else if (depth == 1)
+ else
+#endif
+ if (depth == 1)
{
char *base_addr = GetPixBaseAddr (pixmap);
short row_bytes = GetPixRowBytes (pixmap);
PixMapHandle pixmap = GetGWorldPixMap (ximage);
short depth = GetPixDepth (pixmap);
+#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
if (depth == 32)
{
char *base_addr = GetPixBaseAddr (pixmap);
short row_bytes = GetPixRowBytes (pixmap);
- return ((unsigned long *) (base_addr + y * row_bytes))[x];
+ return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
}
- else if (depth == 1)
+ else
+#endif
+ if (depth == 1)
{
char *base_addr = GetPixBaseAddr (pixmap);
short row_bytes = GetPixRowBytes (pixmap);
{
UnlockPixels (GetGWorldPixMap (ximg));
}
+
+#if USE_CG_DRAWING
+static CGImageRef
+mac_create_cg_image_from_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ Pixmap mask;
+ CGImageRef result = NULL;
+
+ BLOCK_INPUT;
+ if (img->mask)
+ mask = img->mask;
+ else
+ {
+ mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ img->width, img->height, 1);
+ if (mask)
+ {
+ CGrafPtr old_port;
+ GDHandle old_gdh;
+ Rect r;
+
+ GetGWorld (&old_port, &old_gdh);
+ SetGWorld (mask, NULL);
+ BackColor (blackColor); /* Don't mask. */
+ SetRect (&r, 0, 0, img->width, img->height);
+ EraseRect (&r);
+ SetGWorld (old_port, old_gdh);
+ }
+ }
+ if (mask)
+ {
+ CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
+ GetGWorldPixMap (mask), &result);
+ if (mask != img->mask)
+ XFreePixmap (FRAME_X_DISPLAY (f), mask);
+ }
+ UNBLOCK_INPUT;
+
+ return result;
+}
+#endif /* USE_CG_DRAWING */
#endif /* MAC_OS */
id = x_allocate_bitmap_record (f);
#ifdef MAC_OS
dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
- if (! dpyinfo->bitmaps[id - 1].bitmap_data)
- return -1;
bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
#endif /* MAC_OS */
/* Useful functions defined in the section
`Image type independent image structures' below. */
-static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
+static unsigned long four_corners_best P_ ((XImagePtr ximg,
+ int *corners,
+ unsigned long width,
unsigned long height));
static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
return -1;
}
- bg = four_corners_best (ximg, width, height);
+ bg = four_corners_best (ximg, NULL, width, height);
for (y = 0; y < ximg->height; ++y)
{
/* Keywords. */
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata, QCtype;
+extern Lisp_Object QCdata, QCtype, Qcount;
extern Lisp_Object Qcenter;
Lisp_Object QCascent, QCmargin, QCrelief;
Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
return mask;
}
+DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
+ doc: /* Return extension data for image SPEC.
+FRAME is the frame on which the image will be displayed. FRAME nil
+or omitted means use the selected frame. */)
+ (spec, frame)
+ Lisp_Object spec, frame;
+{
+ Lisp_Object ext;
+
+ ext = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ ext = img->data.lisp_val;
+ }
+
+ return ext;
+}
+
\f
/***********************************************************************
Image type independent image structures
img->data.lisp_val = Qnil;
img->ascent = DEFAULT_IMAGE_ASCENT;
img->hash = hash;
+ img->corners[BOT_CORNER] = -1; /* Full image */
return img;
}
type dependent loader function. */
if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
img->load_failed_p = img->type->load (f, img) == 0;
+
+#if defined (MAC_OS) && USE_CG_DRAWING
+ if (!img->load_failed_p && img->data.ptr_val == NULL)
+ {
+ img->data.ptr_val = mac_create_cg_image_from_image (f, img);
+ if (img->data.ptr_val == NULL)
+ {
+ img->load_failed_p = 1;
+ img->type->free (f, img);
+ }
+ }
+#endif
}
On W32, XIMG is assumed to a device context with the bitmap selected. */
static RGB_PIXEL_COLOR
-four_corners_best (ximg, width, height)
+four_corners_best (ximg, corners, width, height)
XImagePtr_or_DC ximg;
+ int *corners;
unsigned long width, height;
{
- RGB_PIXEL_COLOR corners[4], best;
+ RGB_PIXEL_COLOR corner_pixels[4], best;
int i, best_count;
- /* Get the colors at the corners of ximg. */
- corners[0] = GET_PIXEL (ximg, 0, 0);
- corners[1] = GET_PIXEL (ximg, width - 1, 0);
- corners[2] = GET_PIXEL (ximg, width - 1, height - 1);
- corners[3] = GET_PIXEL (ximg, 0, height - 1);
-
+ if (corners && corners[BOT_CORNER] >= 0)
+ {
+ /* Get the colors at the corner_pixels of ximg. */
+ corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
+ corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
+ corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
+ corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
+ }
+ else
+ {
+ /* Get the colors at the corner_pixels of ximg. */
+ corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
+ corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
+ corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
+ corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
+ }
/* Choose the most frequently found color as background. */
for (i = best_count = 0; i < 4; ++i)
{
int j, n;
for (j = n = 0; j < 4; ++j)
- if (corners[i] == corners[j])
+ if (corner_pixels[i] == corner_pixels[j])
++n;
if (n > best_count)
- best = corners[i], best_count = n;
+ best = corner_pixels[i], best_count = n;
}
return best;
#endif /* !HAVE_NTGUI */
}
- img->background = four_corners_best (ximg, img->width, img->height);
+ img->background = four_corners_best (ximg, img->corners, img->width, img->height);
if (free_ximg)
Destroy_Image (ximg, prev);
}
img->background_transparent
- = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN);
+ = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
if (free_mask)
Destroy_Image (mask, prev);
img->colors = NULL;
img->ncolors = 0;
}
+
+#if defined (MAC_OS) && USE_CG_DRAWING
+ if (img->data.ptr_val)
+ {
+ CGImageRelease (img->data.ptr_val);
+ img->data.ptr_val = NULL;
+ }
+#endif
}
/* Free X resources of image IMG which is used on frame F. */
Image Cache
***********************************************************************/
+static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
static void cache_image P_ ((struct frame *f, struct image *img));
static void postprocess_image P_ ((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 (f, spec, hash)
+ struct frame *f;
+ Lisp_Object spec;
+ unsigned hash;
+{
+ struct image *img;
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
+
+ if (!c) return NULL;
+
+ /* If the image spec does not specify a background color, the cached
+ image must have the same background color as the current frame.
+ The foreground color must also match, for the sake of monochrome
+ images.
+
+ In fact, we could ignore the foreground color matching condition
+ for color images, or if the image spec specifies :foreground;
+ similarly we could ignore the background color matching condition
+ for formats that don't use transparency (such as jpeg), or if the
+ image spec specifies :background. However, the extra memory
+ usage is probably negligible in practice, so we don't bother. */
+
+ for (img = c->buckets[i]; img; img = img->next)
+ if (img->hash == hash
+ && !NILP (Fequal (img->spec, spec))
+ && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
+ && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
+ break;
+ return img;
+}
+
+
+/* Search frame F for an image with spec SPEC, and free it. */
+
+static void
+uncache_image (f, spec)
+ struct frame *f;
+ Lisp_Object spec;
+{
+ struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
+ if (img)
+ free_image (f, img);
+}
+
+
/* Free image cache of frame F. Be aware that X frames share images
caches. */
/* Clear image cache of frame F. FORCE_P non-zero means free all
images. FORCE_P zero means clear only images that haven't been
displayed for some time. Should be called from time to time to
- reduce the number of loaded images. If image-eviction-seconds is
- non-nil, this frees images in the cache which weren't displayed for
- at least that many seconds. */
+ reduce the number of loaded images. If image-cache-eviction-delay
+ is non-nil, this frees images in the cache which weren't displayed
+ for at least that many seconds. */
void
clear_image_cache (f, force_p)
}
+DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
+ 1, 2, 0,
+ doc: /* Refresh the image with specification SPEC on frame FRAME.
+If SPEC specifies an image file, the displayed image is updated with
+the current contents of that file.
+FRAME nil or omitted means use the selected frame.
+FRAME t means refresh the image on all frames. */)
+ (spec, frame)
+ Lisp_Object spec, frame;
+{
+ if (!valid_image_p (spec))
+ error ("Invalid image specification");
+
+ if (EQ (frame, Qt))
+ {
+ Lisp_Object tail;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_WINDOW_P (f))
+ uncache_image (f, spec);
+ }
+ }
+ else
+ uncache_image (check_x_frame (frame), spec);
+
+ return Qnil;
+}
+
+
/* Compute masks and transform image IMG on frame F, as specified
by the image's specification, */
struct frame *f;
Lisp_Object spec;
{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
struct image *img;
- int i;
unsigned hash;
struct gcpro gcpro1;
EMACS_TIME now;
/* Look up SPEC in the hash table of the image cache. */
hash = sxhash (spec, 0);
- i = hash % IMAGE_CACHE_BUCKETS_SIZE;
-
- for (img = c->buckets[i]; img; img = img->next)
- if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
- break;
-
+ img = search_image_cache (f, spec, hash);
if (img && img->load_failed_p)
{
free_image (f, img);
img = make_image (spec, hash);
cache_image (f, img);
img->load_failed_p = img->type->load (f, img) == 0;
+ img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
+ img->frame_background = FRAME_BACKGROUND_PIXEL (f);
/* If we can't load the image, and we don't have a width and
height, use some arbitrary width and height so that we can
/* Find image file FILE. Look in data-directory, then
- x-bitmap-file-path. Value is the full name of the file found, or
- nil if not found. */
+ x-bitmap-file-path. Value is the encoded full name of the file
+ found, or nil if not found. */
Lisp_Object
x_find_image_file (file)
if (fd == -1)
file_found = Qnil;
else
- close (fd);
+ {
+ file_found = ENCODE_FILE (file_found);
+ close (fd);
+ }
UNGCPRO;
return file_found;
Lisp_Object specified_file, *file;
FSSpec *fss;
{
-#if MAC_OSX
- FSRef fsr;
-#endif
OSErr err;
+ AEDesc desc;
*file = x_find_image_file (specified_file);
if (!STRINGP (*file))
return fnfErr; /* file or directory not found;
incomplete pathname */
/* Try to open the image file. */
-#if MAC_OSX
- err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
+ err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
+ SBYTES (*file), typeFSS, &desc);
if (err == noErr)
- err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
+ {
+#if TARGET_API_MAC_CARBON
+ err = AEGetDescData (&desc, fss, sizeof (FSSpec));
#else
- err = posix_pathname_to_fsspec (SDATA (*file), fss);
+ *fss = *(FSSpec *)(*(desc.dataHandle));
#endif
+ AEDisposeDesc (&desc);
+ }
return err;
}
struct frame *f;
struct image *img;
OSType type;
- FSSpec *fss;
+ const FSSpec *fss;
Handle dh;
{
- OSErr err;
+ ComponentResult err;
GraphicsImportComponent gi;
Rect rect;
int width, height;
XImagePtr ximg;
RGBColor bg_color;
- err = OpenADefaultComponent (GraphicsImporterComponentType,
- type, &gi);
+ err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
if (err != noErr)
{
image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
UNGCPRO;
return 0;
}
- path = cfstring_create_with_string (file);
+ path = cfstring_create_with_utf8_cstring (SDATA (file));
url = CFURLCreateWithFileSystemPath (NULL, path,
kCFURLPOSIXPathStyle, 0);
CFRelease (path);
if (!check_image_size (f, width, height))
{
+ CGImageRelease (image);
UNGCPRO;
image_error ("Invalid image size", Qnil, Qnil);
return 0;
3. a vector of strings or bool-vectors, one for each line of the
bitmap.
- 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
+ 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
may not be specified in this case because they are defined in the
XBM file.
return bmp;
}
-static void convert_mono_to_color_image (f, img, foreground, background)
+static void
+convert_mono_to_color_image (f, img, foreground, background)
struct frame *f;
struct image *img;
COLORREF foreground, background;
release_frame_dc (f, hdc);
old_prev = SelectObject (old_img_dc, img->pixmap);
new_prev = SelectObject (new_img_dc, new_pixmap);
- SetTextColor (new_img_dc, foreground);
- SetBkColor (new_img_dc, background);
+ /* Windows convention for mono bitmaps is black = background,
+ white = foreground. */
+ SetTextColor (new_img_dc, background);
+ SetBkColor (new_img_dc, foreground);
BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
0, 0, SRCCOPY);
expect_ident ("define");
expect (XBM_TK_IDENT);
- if (LA1 == XBM_TK_NUMBER);
+ if (LA1 == XBM_TK_NUMBER)
{
char *p = strrchr (buffer, '_');
p = p ? p + 1 : buffer;
else
bits = XBOOL_VECTOR (data)->data;
+#ifdef WINDOWSNT
+ {
+ char *invertedBits;
+ int nbytes, i;
+ /* Windows mono bitmaps are reversed compared with X. */
+ invertedBits = bits;
+ nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
+ * img->height;
+ bits = (char *) alloca(nbytes);
+ for (i = 0; i < nbytes; i++)
+ bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
+ }
+#endif
/* Create the pixmap. */
Create_Pixmap_From_Bitmap_Data (f, img, bits,
#endif /* HAVE_XPM || MAC_OS */
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+int
+x_create_bitmap_from_xpm_data (f, bits)
+ struct frame *f;
+ char **bits;
+{
+ Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ int id, rc;
+ XpmAttributes attrs;
+ Pixmap bitmap, mask;
+
+ bzero (&attrs, sizeof attrs);
+
+ attrs.visual = FRAME_X_VISUAL (f);
+ attrs.colormap = FRAME_X_COLORMAP (f);
+ attrs.valuemask |= XpmVisual;
+ attrs.valuemask |= XpmColormap;
+
+ rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ bits, &bitmap, &mask, &attrs);
+ if (rc != XpmSuccess)
+ {
+ XpmFreeAttributes (&attrs);
+ return -1;
+ }
+
+ id = x_allocate_bitmap_record (f);
+ dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+ dpyinfo->bitmaps[id - 1].have_mask = 1;
+ dpyinfo->bitmaps[id - 1].mask = mask;
+ dpyinfo->bitmaps[id - 1].file = NULL;
+ dpyinfo->bitmaps[id - 1].height = attrs.height;
+ dpyinfo->bitmaps[id - 1].width = attrs.width;
+ dpyinfo->bitmaps[id - 1].depth = attrs.depth;
+ dpyinfo->bitmaps[id - 1].refcount = 1;
+
+ XpmFreeAttributes (&attrs);
+ return id;
+}
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
/* Load image IMG which will be displayed on frame F. Value is
non-zero if successful. */
/* XPM support functions for Mac OS where libxpm is not available.
Only XPM version 3 (without any extensions) is supported. */
-static int xpm_scan P_ ((unsigned char **, unsigned char *,
- unsigned char **, int *));
+static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
+ const unsigned char **, int *));
static Lisp_Object xpm_make_color_table_v
- P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
- Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
-static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
+ P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
+ Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
+static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
int, Lisp_Object));
static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
- unsigned char *, int));
+ const unsigned char *, int));
static Lisp_Object xpm_make_color_table_h
- P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
- Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
-static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
+ P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
+ Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
+static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
int, Lisp_Object));
static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
- unsigned char *, int));
-static int xpm_str_to_color_key P_ ((char *));
+ const unsigned char *, int));
+static int xpm_str_to_color_key P_ ((const char *));
static int xpm_load_image P_ ((struct frame *, struct image *,
- unsigned char *, unsigned char *));
+ const unsigned char *, const unsigned char *));
/* Tokens returned from xpm_scan. */
static int
xpm_scan (s, end, beg, len)
- unsigned char **s, *end, **beg;
+ const unsigned char **s, *end, **beg;
int *len;
{
int c;
return XPM_TK_EOF;
}
-/* Functions for color table lookup in XPM data. A Key is a string
+/* Functions for color table lookup in XPM data. A key is a string
specifying the color of each pixel in XPM data. A value is either
an integer that specifies a pixel color, Qt that specifies
transparency, or Qnil for the unspecified color. If the length of
static Lisp_Object
xpm_make_color_table_v (put_func, get_func)
- void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
- Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
+ void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+ Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
{
*put_func = xpm_put_color_table_v;
*get_func = xpm_get_color_table_v;
static void
xpm_put_color_table_v (color_table, chars_start, chars_len, color)
Lisp_Object color_table;
- unsigned char *chars_start;
+ const unsigned char *chars_start;
int chars_len;
Lisp_Object color;
{
static Lisp_Object
xpm_get_color_table_v (color_table, chars_start, chars_len)
Lisp_Object color_table;
- unsigned char *chars_start;
+ const unsigned char *chars_start;
int chars_len;
{
return XVECTOR (color_table)->contents[*chars_start];
static Lisp_Object
xpm_make_color_table_h (put_func, get_func)
- void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
- Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
+ void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+ Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
{
*put_func = xpm_put_color_table_h;
*get_func = xpm_get_color_table_h;
static void
xpm_put_color_table_h (color_table, chars_start, chars_len, color)
Lisp_Object color_table;
- unsigned char *chars_start;
+ const unsigned char *chars_start;
int chars_len;
Lisp_Object color;
{
static Lisp_Object
xpm_get_color_table_h (color_table, chars_start, chars_len)
Lisp_Object color_table;
- unsigned char *chars_start;
+ const unsigned char *chars_start;
int chars_len;
{
struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
XPM_COLOR_KEY_C
};
-static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
+static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
static int
xpm_str_to_color_key (s)
- char *s;
+ const char *s;
{
int i;
xpm_load_image (f, img, contents, end)
struct frame *f;
struct image *img;
- unsigned char *contents, *end;
+ const unsigned char *contents, *end;
{
- unsigned char *s = contents, *beg, *str;
+ const unsigned char *s = contents, *beg, *str;
unsigned char buffer[BUFSIZ];
int width, height, x, y;
int num_colors, chars_per_pixel;
int len, LA1;
- void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
- Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
+ void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+ Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
Lisp_Object frame, color_symbols, color_table;
int best_key, have_mask = 0;
XImagePtr ximg = NULL, mask_img = NULL;
if (color == NULL)
goto failure;
- while (str = strtok (NULL, " \t"))
+ while ((str = strtok (NULL, " \t")) != NULL)
{
next_key = xpm_str_to_color_key (str);
if (next_key >= 0)
Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
- if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
- color_val = Qt;
- else if (x_defined_color (f, SDATA (XCDR (specified_color)),
- &cdef, 0))
- color_val = make_number (cdef.pixel);
+ {
+ if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
+ color_val = Qt;
+ else if (x_defined_color (f, SDATA (XCDR (specified_color)),
+ &cdef, 0))
+ color_val = make_number (cdef.pixel);
+ }
}
if (NILP (color_val) && max_key > 0)
- if (xstricmp (max_color, "None") == 0)
- color_val = Qt;
- else if (x_defined_color (f, max_color, &cdef, 0))
- color_val = make_number (cdef.pixel);
+ {
+ if (xstricmp (max_color, "None") == 0)
+ color_val = Qt;
+ else if (x_defined_color (f, max_color, &cdef, 0))
+ color_val = make_number (cdef.pixel);
+ }
if (!NILP (color_val))
(*put_color_table) (color_table, beg, chars_per_pixel, color_val);
img->width = width;
img->height = height;
+ /* Maybe fill in the background field while we have ximg handy. */
+ if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+ IMAGE_BACKGROUND (img, f, ximg);
+
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
if (have_mask)
created with CreateDIBSection, with the pointer to the bit values
stored in ximg->data. */
-static void XPutPixel (ximg, x, y, color)
+static void
+XPutPixel (ximg, x, y, color)
XImagePtr ximg;
int x, y;
COLORREF color;
GC gc;
#ifdef MAC_OS
-#define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
#define MaskForeground(f) PIX_MASK_DRAW
#else
-#define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
#endif
- gc = XCreateGC_pixmap (dpy, img->pixmap);
+ gc = XCreateGC (dpy, img->pixmap, 0, NULL);
XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
XDrawLine (dpy, img->pixmap, gc, 0, 0,
img->width - 1, img->height - 1);
if (img->mask)
{
- gc = XCreateGC_pixmap (dpy, img->mask);
+ gc = XCreateGC (dpy, img->mask, 0, NULL);
XSetForeground (dpy, gc, MaskForeground (f));
XDrawLine (dpy, img->mask, gc, 0, 0,
img->width - 1, img->height - 1);
}
if (use_img_background)
- bg = four_corners_best (ximg, img->width, img->height);
+ bg = four_corners_best (ximg, img->corners, img->width, img->height);
/* Set all bits in mask_img to 1 whose color in ximg is different
from the background color bg. */
if (raw_p)
{
if ((x & 7) == 0)
- c = *p++;
+ {
+ if (p >= end)
+ {
+ x_destroy_x_image (ximg);
+ x_clear_image (f, img);
+ image_error ("Invalid image size in image `%s'",
+ img->spec, Qnil);
+ goto error;
+ }
+ c = *p++;
+ }
g = c & 0x80;
c <<= 1;
}
}
else
{
+ if (raw_p
+ && ((type == PBM_GRAY)
+ ? (p + height * width > end)
+ : (p + 3 * height * width > end)))
+ {
+ x_destroy_x_image (ximg);
+ x_clear_image (f, img);
+ image_error ("Invalid image size in image `%s'",
+ img->spec, Qnil);
+ goto error;
+ }
+
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
{
{
image_error ("Cannot open image file `%s'", file, Qnil);
UNGCPRO;
- fclose (fp);
return 0;
}
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
}
}
+ /* The commented-out code checked if the png specifies a default
+ background color, and uses that. Since we use the current
+ frame background, it is OK for us to ignore this.
+
else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
- /* Image contains a background color with which to
- combine the image. */
fn_png_set_background (png_ptr, image_bg,
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ */
else
{
/* Image does not contain a background color with which
whenever more data is needed. We read the whole image in one step,
so this only adds a fake end of input marker at the end. */
+static JOCTET our_memory_buffer[2];
+
static boolean
our_memory_fill_input_buffer (cinfo)
j_decompress_ptr cinfo;
{
/* Insert a fake EOI marker. */
struct jpeg_source_mgr *src = cinfo->src;
- static JOCTET buffer[2];
- buffer[0] = (JOCTET) 0xFF;
- buffer[1] = (JOCTET) JPEG_EOI;
+ our_memory_buffer[0] = (JOCTET) 0xFF;
+ our_memory_buffer[1] = (JOCTET) JPEG_EOI;
- src->next_input_byte = buffer;
+ src->next_input_byte = our_memory_buffer;
src->bytes_in_buffer = 2;
return 1;
}
static int gif_image_p P_ ((Lisp_Object object));
static int gif_load P_ ((struct frame *f, struct image *img));
+static void gif_clear_image P_ ((struct frame *f, struct image *img));
/* The symbol `gif' identifying images of this type. */
&Qgif,
gif_image_p,
gif_load,
- x_clear_image,
+ gif_clear_image,
NULL
};
+/* Free X resources of GIF image IMG which is used on frame F. */
+
+static void
+gif_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ /* IMG->data.ptr_val may contain extension data. */
+ img->data.lisp_val = Qnil;
+ x_clear_image (f, img);
+}
+
/* Return non-zero if OBJECT is a valid GIF image specification. */
static int
/* Load GIF image IMG for use on frame F. Value is non-zero if
successful. */
+static int interlace_start[] = {0, 4, 2, 1};
+static int interlace_increment[] = {8, 8, 4, 2};
+
static int
gif_load (f, img)
struct frame *f;
GifFileType *gif;
struct gcpro gcpro1;
Lisp_Object image;
- int ino, image_left, image_top, image_width, image_height;
+ int ino, image_height, image_width;
gif_memory_source memsrc;
unsigned char *raster;
return 0;
}
- image_top = gif->SavedImages[ino].ImageDesc.Top;
- image_left = gif->SavedImages[ino].ImageDesc.Left;
- image_width = gif->SavedImages[ino].ImageDesc.Width;
+ 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[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
+ image_width = gif->SavedImages[ino].ImageDesc.Width;
+ img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
width = img->width = max (gif->SWidth,
max (gif->Image.Left + gif->Image.Width,
- image_left + image_width));
+ img->corners[RIGHT_CORNER]));
height = img->height = max (gif->SHeight,
max (gif->Image.Top + gif->Image.Height,
- image_top + image_height));
+ img->corners[BOT_CORNER]));
if (!check_image_size (f, width, height))
{
init_color_table ();
bzero (pixel_colors, sizeof pixel_colors);
- for (i = 0; i < gif_color_map->ColorCount; ++i)
- {
- 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);
- }
+ if (gif_color_map)
+ for (i = 0; i < gif_color_map->ColorCount; ++i)
+ {
+ 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);
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. */
- for (y = 0; y < image_top; ++y)
+ for (y = 0; y < img->corners[TOP_CORNER]; ++y)
for (x = 0; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (y = image_top + image_height; y < height; ++y)
+ for (y = img->corners[BOT_CORNER]; y < height; ++y)
for (x = 0; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (y = image_top; y < image_top + image_height; ++y)
+ for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
{
- for (x = 0; x < image_left; ++x)
+ for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (x = image_left + image_width; x < width; ++x)
+ for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
if (gif->SavedImages[ino].ImageDesc.Interlace)
{
- static int interlace_start[] = {0, 4, 2, 1};
- static int interlace_increment[] = {8, 8, 4, 2};
int pass;
int row = interlace_start[0];
for (x = 0; x < image_width; x++)
{
int i = raster[(y * image_width) + x];
- XPutPixel (ximg, x + image_left, row + image_top,
- pixel_colors[i]);
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ row + img->corners[TOP_CORNER], pixel_colors[i]);
}
row += interlace_increment[pass];
for (x = 0; x < image_width; ++x)
{
int i = raster[y * image_width + x];
- XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ y + img->corners[TOP_CORNER], pixel_colors[i]);
}
}
+ /* Save GIF image extension data for `image-extension-data'.
+ Format is (count IMAGES FUNCTION "BYTES" ...). */
+ img->data.lisp_val = Qnil;
+ if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+ {
+ ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
+ for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+ /* Append (... FUNCTION "BYTES") */
+ img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+ Fcons (make_number (ext->Function),
+ img->data.lisp_val));
+ img->data.lisp_val = Fnreverse (img->data.lisp_val);
+ }
+ if (gif->ImageCount > 1)
+ img->data.lisp_val = Fcons (Qcount,
+ Fcons (make_number (gif->ImageCount),
+ img->data.lisp_val));
+
fn_DGifCloseFile (gif);
/* Maybe fill in the background field while we have ximg handy. */
RGBColor bg_color;
int width, height;
XImagePtr ximg;
- TimeValue time;
- struct gcpro gcpro1;
+ TimeScale time_scale;
+ TimeValue time, duration;
int ino;
CGrafPtr old_port;
GDHandle old_gdh;
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
+ /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
+ EnterMovies ();
+
if (NILP (specified_data))
{
/* Read from a file */
image, img->spec);
goto error;
}
+ time_scale = GetMediaTimeScale (media);
specified_bg = image_spec_value (img->spec, QCbackground, NULL);
if (!STRINGP (specified_bg) ||
SetGWorld (old_port, old_gdh);
SetMovieActive (movie, 1);
SetMovieGWorld (movie, ximg, NULL);
- SampleNumToMediaTime (media, ino + 1, &time, NULL);
+ SampleNumToMediaTime (media, ino + 1, &time, &duration);
SetMovieTimeValue (movie, time);
MoviesTask (movie, 0L);
DisposeTrackMedia (media);
DisposeMovie (movie);
if (dh)
DisposeHandle (dh);
+
+ /* Save GIF image extension data for `image-extension-data'.
+ Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
+ {
+ Lisp_Object gce = make_uninit_string (4);
+ int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
+
+ /* Fill the delay time field. */
+ SSET (gce, 1, centisec & 0xff);
+ SSET (gce, 2, (centisec >> 8) & 0xff);
+ /* We don't know about other fields. */
+ SSET (gce, 0, 0);
+ SSET (gce, 3, 0);
+
+ img->data.lisp_val = list4 (Qcount, make_number (nsamples),
+ make_number (0xf9), gce);
+ }
+
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
IMAGE_BACKGROUND (img, f, ximg);
defining the supported image types. */
DEFVAR_LISP ("image-types", &Vimage_types,
doc: /* List of potentially supported image types.
-Each element of the list is a symbol for a image type, like 'jpeg or 'png.
+Each element of the list is a symbol for an image type, like 'jpeg or 'png.
To check whether it is really supported, use `image-type-available-p'. */);
Vimage_types = Qnil;
Emacs tries to load the libraries in the order they appear on the
list; if none is loaded, the running session of Emacs won't
support the image type. Types 'pbm and 'xbm don't need to be
-listed; they're always supported. */);
+listed; they are always supported. */);
Vimage_library_alist = Qnil;
Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
defsubr (&Sinit_image_library);
defsubr (&Sclear_image_cache);
+ defsubr (&Simage_refresh);
defsubr (&Simage_size);
defsubr (&Simage_mask_p);
+ defsubr (&Simage_extension_data);
#if GLYPH_DEBUG
defsubr (&Simagep);
DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
doc: /* Non-nil means always draw a cross over disabled images.
-Disabled images are those having an `:conversion disabled' property.
+Disabled images are those having a `:conversion disabled' property.
A cross is always drawn on black & white displays. */);
cross_disabled_images = 0;
void
init_image ()
{
-#ifdef MAC_OS
- /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
- EnterMovies ();
-#ifdef MAC_OSX
+#if defined (MAC_OSX) && TARGET_API_MAC_CARBON
init_image_func_pointer ();
#endif
-#endif
}
/* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9