X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d4aa48db8ed36b1fc7e7b0e6bd35049353f7f96e..ff5dec5cd103f6a9b030d295b014f0ff81025def:/src/image.c diff --git a/src/image.c b/src/image.c index 91be3f4b57..030e06ad77 100644 --- a/src/image.c +++ b/src/image.c @@ -1,14 +1,14 @@ /* Functions for image support on window system. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +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 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #include #include @@ -29,6 +27,16 @@ Boston, MA 02110-1301, USA. */ #include #endif +#ifdef HAVE_PNG +#if defined HAVE_LIBPNG_PNG_H +# include +#else +# include +#endif +#endif + +#include + /* This makes the fields of a Display accessible, in Xlib header files. */ #define XLIB_ILLEGAL_ACCESS @@ -40,9 +48,10 @@ Boston, MA 02110-1301, USA. */ #include "blockinput.h" #include "systime.h" #include -#include "charset.h" +#include "character.h" #include "coding.h" - +#include "termhooks.h" +#include "font.h" #ifdef HAVE_X_WINDOWS #include "xterm.h" @@ -80,51 +89,37 @@ typedef struct w32_bitmap_record Bitmap_Record; #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual #define x_defined_color w32_defined_color #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits) -#endif /* HAVE_NTGUI */ +/* Functions from w32term.c that depend on XColor (so can't go in w32term.h + without modifying lots of files). */ +extern void x_query_colors (struct frame *f, XColor *colors, int ncolors); +extern void x_query_color (struct frame *f, XColor *color); +#endif /* HAVE_NTGUI */ -#ifdef MAC_OS -#include "macterm.h" +#ifdef HAVE_NS +#include "nsterm.h" +#include #include -#ifndef MAC_OSX -#include -#include -#endif -#if TARGET_API_MAC_CARBON -#ifdef MAC_OSX -#include -#else /* not MAC_OSX */ -#include -#endif /* not MAC_OSX */ -#else /* not TARGET_API_MAC_CARBON */ -#include -#include -#include -#include -#include -#endif /* not TARGET_API_MAC_CARBON */ - -/* MAC_TODO : Color tables on Mac. */ + #undef COLOR_TABLE_SUPPORT -#define ZPixmap 0 /* arbitrary */ -typedef struct mac_bitmap_record Bitmap_Record; +typedef struct ns_bitmap_record Bitmap_Record; #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) #define NO_PIXMAP 0 #define RGB_PIXEL_COLOR unsigned long +#define ZPixmap 0 -/* A black pixel in a mask bitmap/pixmap means ``draw a source - pixel''. A white pixel means ``retain the current pixel''. */ -#define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0) -#define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255) - -#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 PIX_MASK_RETAIN 0 +#define PIX_MASK_DRAW 1 -#endif /* MAC_OS */ +#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 +#define DefaultDepthOfScreen(screen) x_display_list->n_planes +#endif /* HAVE_NS */ /* Search path for bitmap files. */ @@ -155,174 +150,32 @@ static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p)); the bitmaps yourself. That is, creating a bitmap from the same data more than once will not be caught. */ -#ifdef MAC_OS - -static XImagePtr -XGetImage (display, pixmap, x, y, width, height, plane_mask, format) - Display *display; /* not used */ - Pixmap pixmap; - int x, y; /* not used */ - unsigned int width, height; /* not used */ - unsigned long plane_mask; /* not used */ - int format; /* not used */ +#ifdef HAVE_NS +XImagePtr +XGetImage (Display *display, Pixmap pixmap, int x, int y, + unsigned int width, unsigned int height, + unsigned long plane_mask, int format) { -#if GLYPH_DEBUG - xassert (x == 0 && y == 0); - { - Rect ri, rp; - SetRect (&ri, 0, 0, width, height); - xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp))); - } - xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap)))); -#endif - - LockPixels (GetGWorldPixMap (pixmap)); - + /* TODO: not sure what this function is supposed to do.. */ + ns_retain_object(pixmap); return pixmap; } -static void -XPutPixel (ximage, x, y, pixel) - XImagePtr ximage; - int x, y; - unsigned long pixel; +/* use with imgs created by ns_image_for_XPM */ +unsigned long +XGetPixel (XImagePtr ximage, int x, int y) { - PixMapHandle pixmap = GetGWorldPixMap (ximage); - short depth = GetPixDepth (pixmap); - -#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING - if (depth == 32) - { - char *base_addr = GetPixBaseAddr (pixmap); - short row_bytes = GetPixRowBytes (pixmap); - - ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel; - } - else -#endif - if (depth == 1) - { - char *base_addr = GetPixBaseAddr (pixmap); - short row_bytes = GetPixRowBytes (pixmap); - - if (pixel == PIX_MASK_DRAW) - base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7); - else - base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7)); - } - else - { - CGrafPtr old_port; - GDHandle old_gdh; - RGBColor color; - - GetGWorld (&old_port, &old_gdh); - SetGWorld (ximage, NULL); - - color.red = RED16_FROM_ULONG (pixel); - color.green = GREEN16_FROM_ULONG (pixel); - color.blue = BLUE16_FROM_ULONG (pixel); - - SetCPixel (x, y, &color); - - SetGWorld (old_port, old_gdh); - } -} - -static unsigned long -XGetPixel (ximage, x, y) - XImagePtr ximage; - int x, y; -{ - PixMapHandle pixmap = GetGWorldPixMap (ximage); - short depth = GetPixDepth (pixmap); - -#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING - if (depth == 32) - { - char *base_addr = GetPixBaseAddr (pixmap); - short row_bytes = GetPixRowBytes (pixmap); - - return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff; - } - else -#endif - if (depth == 1) - { - char *base_addr = GetPixBaseAddr (pixmap); - short row_bytes = GetPixRowBytes (pixmap); - - if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7))) - return PIX_MASK_DRAW; - else - return PIX_MASK_RETAIN; - } - else - { - CGrafPtr old_port; - GDHandle old_gdh; - RGBColor color; - - GetGWorld (&old_port, &old_gdh); - SetGWorld (ximage, NULL); - - GetCPixel (x, y, &color); - - SetGWorld (old_port, old_gdh); - return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8); - } + return ns_get_pixel(ximage, x, y); } -static void -XDestroyImage (ximg) - XImagePtr ximg; -{ - UnlockPixels (GetGWorldPixMap (ximg)); -} - -#if USE_CG_DRAWING -static CGImageRef -mac_create_cg_image_from_image (f, img) - struct frame *f; - struct image *img; +/* use with imgs created by ns_image_for_XPM; alpha set to 1; + pixel is assumed to be in form RGB */ +void +XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) { - 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; + ns_put_pixel(ximage, x, y, pixel); } -#endif /* USE_CG_DRAWING */ -#endif /* MAC_OS */ +#endif /* HAVE_NS */ /* Functions to access the contents of a bitmap, given an id. */ @@ -434,17 +287,18 @@ x_create_bitmap_from_data (f, bits, width, height) return -1; #endif /* HAVE_NTGUI */ -#ifdef MAC_OS - /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */ - if (width % 16 != 0) - return -1; +#ifdef HAVE_NS + void *bitmap = ns_image_from_XBM(bits, width, height); + if (!bitmap) + return -1; #endif id = x_allocate_bitmap_record (f); -#ifdef MAC_OS - dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width); - bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width); -#endif /* MAC_OS */ + +#ifdef HAVE_NS + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].depth = 1; +#endif dpyinfo->bitmaps[id - 1].file = NULL; dpyinfo->bitmaps[id - 1].height = height; @@ -473,16 +327,32 @@ x_create_bitmap_from_file (f, file) struct frame *f; Lisp_Object file; { -#ifdef MAC_OS - return -1; /* MAC_TODO : bitmap support */ -#endif /* MAC_OS */ + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); #ifdef HAVE_NTGUI return -1; /* W32_TODO : bitmap support */ #endif /* HAVE_NTGUI */ +#ifdef HAVE_NS + int id; + void *bitmap = ns_image_from_file(file); + + if (!bitmap) + return -1; + + + 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].depth = 1; + dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap); + dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap); + strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file)); + return id; +#endif + #ifdef HAVE_X_WINDOWS - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); unsigned int width, height; Pixmap bitmap; int xhot, yhot, result, id; @@ -546,10 +416,9 @@ free_bitmap_record (dpyinfo, bm) DeleteObject (bm->pixmap); #endif /* HAVE_NTGUI */ -#ifdef MAC_OS - xfree (bm->bitmap_data); /* Added ++kfs */ - bm->bitmap_data = NULL; -#endif /* MAC_OS */ +#ifdef HAVE_NS + ns_release_object(bm->img); +#endif if (bm->file) { @@ -735,7 +604,7 @@ Lisp_Object Qxbm; extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; extern Lisp_Object QCdata, QCtype; extern Lisp_Object Qcenter; -Lisp_Object QCascent, QCmargin, QCrelief, Qcount; +Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; @@ -1142,8 +1011,8 @@ or omitted means use the selected frame. */) return mask; } -DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0, - doc: /* Return extension data for image SPEC. +DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0, + doc: /* Return metadata for image SPEC. FRAME is the frame on which the image will be displayed. FRAME nil or omitted means use the selected frame. */) (spec, frame) @@ -1184,9 +1053,11 @@ make_image (spec, hash) unsigned hash; { struct image *img = (struct image *) xmalloc (sizeof *img); + Lisp_Object file = image_spec_value (spec, QCfile, NULL); xassert (valid_image_p (spec)); bzero (img, sizeof *img); + img->dependencies = NILP (file) ? Qnil : list1 (file); img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL)); xassert (img->type != NULL); img->spec = spec; @@ -1207,7 +1078,7 @@ free_image (f, img) { if (img) { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); /* Remove IMG from the hash table of its cache. */ if (img->prev) @@ -1279,17 +1150,6 @@ prepare_image_for_display (f, img) 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 } @@ -1326,7 +1186,8 @@ image_ascent (img, face, slice) 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 + face->font->ascent - face->font->descent + 1) / 2; + ascent = (height + FONT_BASE(face->font) + - FONT_DESCENT(face->font) + 1) / 2; #endif /* HAVE_NTGUI */ } else @@ -1395,6 +1256,14 @@ four_corners_best (ximg, corners, width, height) #define Free_Pixmap(display, pixmap) \ DeleteObject (pixmap) +#elif defined (HAVE_NS) + +#define Destroy_Image(ximg, dummy) \ + ns_release_object(ximg) + +#define Free_Pixmap(display, pixmap) \ + ns_release_object(pixmap) + #else #define Destroy_Image(ximg, dummy) \ @@ -1403,7 +1272,7 @@ four_corners_best (ximg, corners, width, height) #define Free_Pixmap(display, pixmap) \ XFreePixmap (display, pixmap) -#endif /* HAVE_NTGUI */ +#endif /* !HAVE_NTGUI && !HAVE_NS */ /* Return the `background' field of IMG. If IMG doesn't have one yet, @@ -1526,6 +1395,7 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p) { Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); img->pixmap = NO_PIXMAP; + /* NOTE (HAVE_NS): background color is NOT an indexed color! */ img->background_valid = 0; } @@ -1538,7 +1408,6 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p) if (colors_p && img->ncolors) { - /* MAC_TODO: color table support. */ /* W32_TODO: color table support. */ #ifdef HAVE_X_WINDOWS x_free_colors (f, img->colors, img->ncolors); @@ -1548,13 +1417,6 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p) 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. */ @@ -1642,7 +1504,7 @@ search_image_cache (f, spec, hash) unsigned hash; { struct image *img; - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); int i = hash % IMAGE_CACHE_BUCKETS_SIZE; if (!c) return NULL; @@ -1689,7 +1551,7 @@ void free_image_cache (f) struct frame *f; { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); if (c) { int i; @@ -1702,26 +1564,25 @@ free_image_cache (f) xfree (c->images); xfree (c->buckets); xfree (c); - FRAME_X_IMAGE_CACHE (f) = NULL; + FRAME_IMAGE_CACHE (f) = NULL; } } -/* 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-cache-eviction-delay - is non-nil, this frees images in the cache which weren't displayed - for at least that many seconds. */ +/* Clear image cache of frame F. FILTER=t means free all images. + FILTER=nil means clear only images that haven't been + displayed for some time. + Else, only free the images which have FILTER in their `dependencies'. + Should be called from time to time to 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) - struct frame *f; - int force_p; +clear_image_cache (struct frame *f, Lisp_Object filter) { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); - if (c && INTEGERP (Vimage_cache_eviction_delay)) + if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay))) { EMACS_TIME t; unsigned long old; @@ -1738,7 +1599,9 @@ clear_image_cache (f, force_p) { struct image *img = c->images[i]; if (img != NULL - && (force_p || img->timestamp < old)) + && (NILP (filter) ? img->timestamp < old + : (EQ (Qt, filter) + || !NILP (Fmember (filter, img->dependencies))))) { free_image (f, img); ++nfreed; @@ -1756,8 +1619,7 @@ clear_image_cache (f, force_p) FOR_EACH_FRAME (tail, frame) { struct frame *f = XFRAME (frame); - if (FRAME_WINDOW_P (f) - && FRAME_X_IMAGE_CACHE (f) == c) + if (FRAME_IMAGE_CACHE (f) == c) clear_current_matrices (f); } @@ -1768,25 +1630,33 @@ clear_image_cache (f, force_p) } } +void +clear_image_caches (Lisp_Object filter) +{ + /* FIXME: We want to do + * struct terminal *t; + * for (t = terminal_list; t; t = t->next_terminal) + * clear_image_cache (t, filter); */ + Lisp_Object tail, frame; + FOR_EACH_FRAME (tail, frame) + if (FRAME_WINDOW_P (XFRAME (frame))) + clear_image_cache (XFRAME (frame), filter); +} DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache, 0, 1, 0, - doc: /* Clear the image cache of FRAME. -FRAME nil or omitted means use the selected frame. -FRAME t means clear the image caches of all frames. */) - (frame) - Lisp_Object frame; -{ - if (EQ (frame, Qt)) - { - Lisp_Object tail; - - FOR_EACH_FRAME (tail, frame) - if (FRAME_WINDOW_P (XFRAME (frame))) - clear_image_cache (XFRAME (frame), 1); - } + doc: /* Clear the image cache. +FILTER nil or a frame means clear all images in the selected frame. +FILTER t means clear the image caches of all frames. +Anything else, means only clear those images which refer to FILTER, +which is then usually a filename. */) + (filter) + Lisp_Object filter; +{ + if (!(EQ (filter, Qnil) || FRAMEP (filter))) + clear_image_caches (filter); else - clear_image_cache (check_x_frame (frame), 1); + clear_image_cache (check_x_frame (filter), Qt); return Qnil; } @@ -1916,7 +1786,7 @@ lookup_image (f, spec) xassert (FRAME_WINDOW_P (f)); xassert (valid_image_p (spec)); - c = FRAME_X_IMAGE_CACHE (f); + c = FRAME_IMAGE_CACHE (f); GCPRO1 (spec); @@ -2027,7 +1897,7 @@ cache_image (f, img) struct frame *f; struct image *img; { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); int i; /* Find a free slot in c->images. */ @@ -2062,28 +1932,36 @@ cache_image (f, img) /* Call FN on every image in the image cache of frame F. Used to mark Lisp Objects in the image cache. */ +/* Mark Lisp objects in image IMG. */ + +static void +mark_image (img) + struct image *img; +{ + mark_object (img->spec); + mark_object (img->dependencies); + + if (!NILP (img->data.lisp_val)) + mark_object (img->data.lisp_val); +} + + void -forall_images_in_image_cache (f, fn) - struct frame *f; - void (*fn) P_ ((struct image *img)); +mark_image_cache (struct image_cache *c) { - if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)) + if (c) { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); - if (c) - { - int i; - for (i = 0; i < c->used; ++i) - if (c->images[i]) - fn (c->images[i]); - } + int i; + for (i = 0; i < c->used; ++i) + if (c->images[i]) + mark_image (c->images[i]); } } /*********************************************************************** - X / MAC / W32 support code + X / NS / W32 support code ***********************************************************************/ #ifdef HAVE_NTGUI @@ -2268,26 +2146,17 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap) #endif /* HAVE_NTGUI */ -#ifdef MAC_OS - Display *display = FRAME_X_DISPLAY (f); - Window window = FRAME_X_WINDOW (f); - - xassert (interrupt_input_blocked); - - /* Allocate a pixmap of the same size. */ - *pixmap = XCreatePixmap (display, window, width, height, depth); - if (*pixmap == NO_PIXMAP) +#ifdef HAVE_NS + *pixmap = ns_image_for_XPM(width, height, depth); + if (*pixmap == 0) { *ximg = NULL; - image_error ("Unable to create X pixmap", Qnil, Qnil); + image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil); return 0; } - - LockPixels (GetGWorldPixMap (*pixmap)); *ximg = *pixmap; return 1; - -#endif /* MAC_OS */ +#endif } @@ -2310,9 +2179,9 @@ x_destroy_x_image (ximg) ximg->data = NULL; xfree (ximg); #endif /* HAVE_NTGUI */ -#ifdef MAC_OS - XDestroyImage (ximg); -#endif /* MAC_OS */ +#ifdef HAVE_NS + ns_release_object(ximg); +#endif /* HAVE_NS */ } } @@ -2344,9 +2213,10 @@ x_put_x_image (f, ximg, pixmap, width, height) #endif #endif /* HAVE_NTGUI */ -#ifdef MAC_OS +#ifdef HAVE_NS xassert (ximg == pixmap); -#endif /* MAC_OS */ + ns_retain_object(ximg); +#endif } @@ -2388,407 +2258,46 @@ x_find_image_file (file) close (fd); } - UNGCPRO; - return file_found; -} - - -/* Read FILE into memory. Value is a pointer to a buffer allocated - with xmalloc holding FILE's contents. Value is null if an error - occurred. *SIZE is set to the size of the file. */ - -static unsigned char * -slurp_file (file, size) - char *file; - int *size; -{ - FILE *fp = NULL; - unsigned char *buf = NULL; - struct stat st; - - if (stat (file, &st) == 0 - && (fp = fopen (file, "rb")) != NULL - && (buf = (unsigned char *) xmalloc (st.st_size), - fread (buf, 1, st.st_size, fp) == st.st_size)) - { - *size = st.st_size; - fclose (fp); - } - else - { - if (fp) - fclose (fp); - if (buf) - { - xfree (buf); - buf = NULL; - } - } - - return buf; -} - - - -#ifdef MAC_OS - -/*********************************************************************** - MAC Image Load Functions - ***********************************************************************/ - -static int image_load_quicktime P_ ((struct frame *, struct image *img, - OSType)); -#ifdef MAC_OSX -static int image_load_quartz2d P_ ((struct frame *, struct image *img, int)); -#endif - -static OSErr -find_image_fsspec (specified_file, file, fss) - Lisp_Object specified_file, *file; - FSSpec *fss; -{ - 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. */ - err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file), - SBYTES (*file), typeFSS, &desc); - if (err == noErr) - { -#if TARGET_API_MAC_CARBON - err = AEGetDescData (&desc, fss, sizeof (FSSpec)); -#else - *fss = *(FSSpec *)(*(desc.dataHandle)); -#endif - AEDisposeDesc (&desc); - } - return err; -} - -static int -image_load_qt_1 (f, img, type, fss, dh) - struct frame *f; - struct image *img; - OSType type; - const FSSpec *fss; - Handle dh; -{ - ComponentResult err; - GraphicsImportComponent gi; - Rect rect; - int width, height; - ImageDescriptionHandle desc_handle; - short draw_all_pixels; - Lisp_Object specified_bg; - XColor color; - XImagePtr ximg; - RGBColor bg_color; - - err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi); - if (err != noErr) - { - image_error ("Cannot get importer component for `%s'", img->spec, Qnil); - return 0; - } - if (dh == NULL) - { - /* read from file system spec */ - err = GraphicsImportSetDataFile (gi, fss); - if (err != noErr) - { - image_error ("Cannot set fsspec to graphics importer for '%s'", - img->spec, Qnil); - goto error; - } - } - else - { - /* read from data handle */ - err = GraphicsImportSetDataHandle (gi, dh); - if (err != noErr) - { - image_error ("Cannot set data handle to graphics importer for `%s'", - img->spec, Qnil); - goto error; - } - } - err = GraphicsImportGetImageDescription (gi, &desc_handle); - if (err != noErr || desc_handle == NULL) - { - image_error ("Error reading `%s'", img->spec, Qnil); - goto error; - } - width = img->width = (*desc_handle)->width; - height = img->height = (*desc_handle)->height; - DisposeHandle ((Handle)desc_handle); - - if (!check_image_size (f, width, height)) - { - image_error ("Invalid image size", Qnil, Qnil); - goto error; - } - - err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels); -#if 0 - /* Don't check the error code here. It may have an undocumented - value -32766. */ - if (err != noErr) - { - image_error ("Error reading `%s'", img->spec, Qnil); - goto error; - } -#endif - if (draw_all_pixels != graphicsImporterDrawsAllPixels) - { - specified_bg = image_spec_value (img->spec, QCbackground, NULL); - if (!STRINGP (specified_bg) || - !mac_defined_color (f, SDATA (specified_bg), &color, 0)) - { - color.pixel = FRAME_BACKGROUND_PIXEL (f); - color.red = RED16_FROM_ULONG (color.pixel); - color.green = GREEN16_FROM_ULONG (color.pixel); - color.blue = BLUE16_FROM_ULONG (color.pixel); - } - } - - if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) - goto error; - if (draw_all_pixels != graphicsImporterDrawsAllPixels) - { - CGrafPtr old_port; - GDHandle old_gdh; - - GetGWorld (&old_port, &old_gdh); - SetGWorld (ximg, NULL); - bg_color.red = color.red; - bg_color.green = color.green; - bg_color.blue = color.blue; - RGBBackColor (&bg_color); -#if TARGET_API_MAC_CARBON - GetPortBounds (ximg, &rect); - EraseRect (&rect); -#else - EraseRect (&(ximg->portRect)); -#endif - SetGWorld (old_port, old_gdh); - } - GraphicsImportSetGWorld (gi, ximg, NULL); - GraphicsImportDraw (gi); - CloseComponent (gi); - - /* 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); - - /* Put the image into the pixmap. */ - x_put_x_image (f, ximg, img->pixmap, width, height); - x_destroy_x_image (ximg); - return 1; - - error: - CloseComponent (gi); - return 0; -} - - -/* Load an image using the QuickTime Graphics Importer. - Note: The alpha channel does not work for PNG images. */ -static int -image_load_quicktime (f, img, type) - struct frame *f; - struct image *img; - OSType type; -{ - Lisp_Object specified_file; - Lisp_Object specified_data; - OSErr err; - - specified_file = image_spec_value (img->spec, QCfile, NULL); - specified_data = image_spec_value (img->spec, QCdata, NULL); - - if (NILP (specified_data)) - { - /* Read from a file */ - Lisp_Object file; - FSSpec fss; - - err = find_image_fsspec (specified_file, &file, &fss); - if (err != noErr) - { - if (err == fnfErr) - image_error ("Cannot find image file `%s'", specified_file, Qnil); - else - image_error ("Cannot open `%s'", file, Qnil); - return 0; - } - return image_load_qt_1 (f, img, type, &fss, NULL); - } - else - { - /* Memory source! */ - int success_p; - Handle dh; - - err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data)); - if (err != noErr) - { - image_error ("Cannot allocate data handle for `%s'", - img->spec, Qnil); - return 0; - } - success_p = image_load_qt_1 (f, img, type, NULL, dh); - DisposeHandle (dh); - return success_p; - } -} - - -#ifdef MAC_OSX -/* Load a PNG/JPEG image using Quartz 2D decoding routines. - CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2. - So don't use this function directly but determine at runtime - whether it exists. */ -typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType) - (CGDataProviderRef, const float [], bool, CGColorRenderingIntent); -static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider; - - -static void -init_image_func_pointer () -{ - if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider")) - { - MyCGImageCreateWithPNGDataProvider - = (CGImageCreateWithPNGDataProviderProcType) - NSAddressOfSymbol (NSLookupAndBindSymbol - ("_CGImageCreateWithPNGDataProvider")); - } - else - MyCGImageCreateWithPNGDataProvider = NULL; -} - - -static int -image_load_quartz2d (f, img, png_p) - struct frame *f; - struct image *img; - int png_p; -{ - Lisp_Object file, specified_file; - Lisp_Object specified_data, specified_bg; - struct gcpro gcpro1; - CGDataProviderRef source; - CGImageRef image; - int width, height; - XColor color; - XImagePtr ximg = NULL; - CGContextRef context; - CGRect rectangle; - - /* Open the file. */ - specified_file = image_spec_value (img->spec, QCfile, NULL); - specified_data = image_spec_value (img->spec, QCdata, NULL); - - file = Qnil; - GCPRO1 (file); - - if (NILP (specified_data)) - { - CFStringRef path; - CFURLRef url; - - file = x_find_image_file (specified_file); - if (!STRINGP (file)) - { - image_error ("Cannot find image file `%s'", specified_file, Qnil); - UNGCPRO; - return 0; - } - path = cfstring_create_with_utf8_cstring (SDATA (file)); - url = CFURLCreateWithFileSystemPath (NULL, path, - kCFURLPOSIXPathStyle, 0); - CFRelease (path); - source = CGDataProviderCreateWithURL (url); - CFRelease (url); - } - else - source = CGDataProviderCreateWithData (NULL, SDATA (specified_data), - SBYTES (specified_data), NULL); - - if (png_p) - image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE, - kCGRenderingIntentDefault); - else - image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE, - kCGRenderingIntentDefault); + UNGCPRO; + return file_found; +} - CGDataProviderRelease (source); - if (image == NULL) - { - UNGCPRO; - image_error ("Error reading image `%s'", img->spec, Qnil); - return 0; - } - width = img->width = CGImageGetWidth (image); - height = img->height = CGImageGetHeight (image); - if (!check_image_size (f, width, height)) - { - CGImageRelease (image); - UNGCPRO; - image_error ("Invalid image size", Qnil, Qnil); - return 0; - } +/* Read FILE into memory. Value is a pointer to a buffer allocated + with xmalloc holding FILE's contents. Value is null if an error + occurred. *SIZE is set to the size of the file. */ - if (png_p) - { - specified_bg = image_spec_value (img->spec, QCbackground, NULL); - if (!STRINGP (specified_bg) || - !mac_defined_color (f, SDATA (specified_bg), &color, 0)) - { - color.pixel = FRAME_BACKGROUND_PIXEL (f); - color.red = RED16_FROM_ULONG (color.pixel); - color.green = GREEN16_FROM_ULONG (color.pixel); - color.blue = BLUE16_FROM_ULONG (color.pixel); - } - } +static unsigned char * +slurp_file (file, size) + char *file; + int *size; +{ + FILE *fp = NULL; + unsigned char *buf = NULL; + struct stat st; - if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) + if (stat (file, &st) == 0 + && (fp = fopen (file, "rb")) != NULL + && (buf = (unsigned char *) xmalloc (st.st_size), + fread (buf, 1, st.st_size, fp) == st.st_size)) { - CGImageRelease (image); - UNGCPRO; - return 0; + *size = st.st_size; + fclose (fp); } - rectangle = CGRectMake (0, 0, width, height); - QDBeginCGContext (ximg, &context); - if (png_p) + else { - CGContextSetRGBFillColor (context, color.red / 65535.0, - color.green / 65535.0, - color.blue / 65535.0, 1.0); - CGContextFillRect (context, rectangle); + if (fp) + fclose (fp); + if (buf) + { + xfree (buf); + buf = NULL; + } } - CGContextDrawImage (context, rectangle, image); - QDEndCGContext (ximg, &context); - CGImageRelease (image); - - /* 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); - /* Put the image into the pixmap. */ - x_put_x_image (f, ximg, img->pixmap, width, height); - x_destroy_x_image (ximg); - UNGCPRO; - return 1; + return buf; } -#endif -#endif /* MAC_OS */ /*********************************************************************** @@ -2802,7 +2311,7 @@ static int xbm_load_image P_ ((struct frame *f, struct image *img, static int xbm_image_p P_ ((Lisp_Object object)); static int xbm_read_bitmap_data P_ ((struct frame *f, unsigned char *, unsigned char *, - int *, int *, unsigned char **)); + int *, int *, unsigned char **, int)); static int xbm_file_p P_ ((Lisp_Object)); @@ -2829,7 +2338,7 @@ enum xbm_keyword_index /* Vector of image_keyword structures describing the format of valid XBM image specifications. */ -static struct image_keyword xbm_format[XBM_LAST] = +static const struct image_keyword xbm_format[XBM_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":file", IMAGE_STRING_VALUE, 0}, @@ -3128,6 +2637,8 @@ convert_mono_to_color_image (f, img, foreground, background) release_frame_dc (f, hdc); old_prev = SelectObject (old_img_dc, img->pixmap); new_prev = SelectObject (new_img_dc, new_pixmap); + /* Windows convention for mono bitmaps is black = background, + white = foreground. */ SetTextColor (new_img_dc, background); SetBkColor (new_img_dc, foreground); @@ -3169,6 +2680,10 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors) /* If colors were specified, transfer the bitmap to a color one. */ if (non_default_colors) convert_mono_to_color_image (f, img, fg, bg); + +#elif defined (HAVE_NS) + img->pixmap = ns_image_from_XBM(data, img->width, img->height); + #else img->pixmap = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), @@ -3177,7 +2692,7 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors) img->width, img->height, fg, bg, DefaultDepthOfScreen (FRAME_X_SCREEN (f))); -#endif /* HAVE_NTGUI */ +#endif /* !HAVE_NTGUI && !HAVE_NS */ } @@ -3187,14 +2702,17 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors) buffer's end. Set *WIDTH and *HEIGHT to the width and height of the image. Return in *DATA the bitmap data allocated with xmalloc. Value is non-zero if successful. DATA null means just test if - CONTENTS looks like an in-memory XBM file. */ + CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR + is non-zero, inhibit the call to image_error when the image size is + invalid (the bitmap remains unread). */ static int -xbm_read_bitmap_data (f, contents, end, width, height, data) +xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error) struct frame *f; unsigned char *contents, *end; int *width, *height; unsigned char **data; + int inhibit_image_error; { unsigned char *s = contents; char buffer[BUFSIZ]; @@ -3245,7 +2763,11 @@ xbm_read_bitmap_data (f, contents, end, width, height, data) } if (!check_image_size (f, *width, *height)) - goto failure; + { + if (!inhibit_image_error) + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + goto failure; + } else if (data == NULL) goto success; @@ -3348,7 +2870,8 @@ xbm_load_image (f, img, contents, end) unsigned char *data; int success_p = 0; - rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data); + rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, + &data, 0); if (rc) { unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); @@ -3403,9 +2926,8 @@ xbm_file_p (data) int w, h; return (STRINGP (data) && xbm_read_bitmap_data (NULL, SDATA (data), - (SDATA (data) - + SBYTES (data)), - &w, &h, NULL)); + (SDATA (data) + SBYTES (data)), + &w, &h, NULL, 1)); } @@ -3523,6 +3045,19 @@ xbm_load (f, img) 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, @@ -3548,13 +3083,13 @@ xbm_load (f, img) XPM images ***********************************************************************/ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (HAVE_NS) static int xpm_image_p P_ ((Lisp_Object object)); static int xpm_load P_ ((struct frame *f, struct image *img)); static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); -#endif /* HAVE_XPM || MAC_OS */ +#endif /* HAVE_XPM || HAVE_NS */ #ifdef HAVE_XPM #ifdef HAVE_NTGUI @@ -3577,7 +3112,7 @@ static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); #endif /* HAVE_NTGUI */ #endif /* HAVE_XPM */ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (HAVE_NS) /* The symbol `xpm' identifying XPM-format images. */ Lisp_Object Qxpm; @@ -3603,7 +3138,7 @@ enum xpm_keyword_index /* Vector of image_keyword structures describing the format of valid XPM image specifications. */ -static struct image_keyword xpm_format[XPM_LAST] = +static const struct image_keyword xpm_format[XPM_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":file", IMAGE_STRING_VALUE, 0}, @@ -3904,7 +3439,7 @@ xpm_image_p (object) || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); } -#endif /* HAVE_XPM || MAC_OS */ +#endif /* HAVE_XPM || HAVE_NS */ #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) int @@ -4183,9 +3718,9 @@ xpm_load (f, img) #endif /* HAVE_XPM */ -#ifdef MAC_OS +#if defined (HAVE_NS) && !defined (HAVE_XPM) -/* XPM support functions for Mac OS where libxpm is not available. +/* XPM support functions for NS where libxpm is not available. Only XPM version 3 (without any extensions) is supported. */ static int xpm_scan P_ ((const unsigned char **, const unsigned char *, @@ -4242,8 +3777,8 @@ xpm_scan (s, end, beg, len) if (isalpha (c) || c == '_' || c == '-' || c == '+') { *beg = *s - 1; - while (*s < end && - (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+')) + while (*s < end + && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+')) ++*s; *len = *s - *beg; return XPM_TK_IDENT; @@ -4442,7 +3977,7 @@ xpm_load_image (f, img, contents, end) if (!check_image_size (f, width, height)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); goto failure; } @@ -4519,7 +4054,7 @@ xpm_load_image (f, img, contents, end) if (CONSP (specified_color) && STRINGP (XCDR (specified_color))) { - if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0) + if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0) color_val = Qt; else if (x_defined_color (f, SDATA (XCDR (specified_color)), &cdef, 0)) @@ -4528,7 +4063,7 @@ xpm_load_image (f, img, contents, end) } if (NILP (color_val) && max_key > 0) { - if (xstricmp (max_color, "None") == 0) + if (xstrcasecmp (max_color, "None") == 0) color_val = Qt; else if (x_defined_color (f, max_color, &cdef, 0)) color_val = make_number (cdef.pixel); @@ -4541,8 +4076,11 @@ xpm_load_image (f, img, contents, end) if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap) +#ifndef HAVE_NS || !x_create_x_image_and_pixmap (f, width, height, 1, - &mask_img, &img->mask)) + &mask_img, &img->mask) +#endif + ) { image_error ("Out of memory (%s)", img->spec, Qnil); goto error; @@ -4562,9 +4100,14 @@ xpm_load_image (f, img, contents, end) XPutPixel (ximg, x, y, (INTEGERP (color_val) ? XINT (color_val) : FRAME_FOREGROUND_PIXEL (f))); +#ifndef HAVE_NS XPutPixel (mask_img, x, y, (!EQ (color_val, Qt) ? PIX_MASK_DRAW : (have_mask = 1, PIX_MASK_RETAIN))); +#else + if (EQ(color_val, Qt)) + ns_set_alpha(ximg, x, y, 0); +#endif } if (y + 1 < height) expect (','); @@ -4579,6 +4122,7 @@ xpm_load_image (f, img, contents, end) x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); +#ifndef HAVE_NS if (have_mask) { /* Fill in the background_transparent field while we have the @@ -4594,7 +4138,7 @@ xpm_load_image (f, img, contents, end) Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); img->mask = NO_PIXMAP; } - +#endif return 1; failure: @@ -4660,7 +4204,7 @@ xpm_load (f, img) return success_p; } -#endif /* MAC_OS */ +#endif /* HAVE_NS && !HAVE_XPM */ @@ -4921,15 +4465,13 @@ lookup_rgb_color (f, r, g, b) { unsigned long pixel; -#ifdef MAC_OS - pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8); - gamma_correct (f, &pixel); -#endif /* MAC_OS */ - #ifdef HAVE_NTGUI pixel = PALETTERGB (r >> 8, g >> 8, b >> 8); #endif /* HAVE_NTGUI */ +#ifdef HAVE_NS + pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8); +#endif /* HAVE_NS */ return pixel; } @@ -5021,9 +4563,9 @@ x_to_xcolors (f, img, rgb_p) { XColor *row = p; -#ifdef HAVE_X_WINDOWS +#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) for (x = 0; x < img->width; ++x, ++p) - p->pixel = XGetPixel (ximg, x, y); + p->pixel = GET_PIXEL (ximg, x, y); if (rgb_p) x_query_colors (f, row, img->width); @@ -5035,16 +4577,9 @@ x_to_xcolors (f, img, rgb_p) p->pixel = GET_PIXEL (ximg, x, y); if (rgb_p) { -#ifdef MAC_OS p->red = RED16_FROM_ULONG (p->pixel); p->green = GREEN16_FROM_ULONG (p->pixel); p->blue = BLUE16_FROM_ULONG (p->pixel); -#endif /* MAC_OS */ -#ifdef HAVE_NTGUI - p->red = 256 * GetRValue (p->pixel); - p->green = 256 * GetGValue (p->pixel); - p->blue = 256 * GetBValue (p->pixel); -#endif /* HAVE_NTGUI */ } } #endif /* HAVE_X_WINDOWS */ @@ -5116,7 +4651,7 @@ x_from_xcolors (f, img, colors) XColor *colors; { int x, y; - XImagePtr oimg; + XImagePtr oimg = NULL; Pixmap pixmap; XColor *p; @@ -5330,11 +4865,9 @@ x_disable_image (f, img) Display *dpy = FRAME_X_DISPLAY (f); GC gc; -#ifdef MAC_OS -#define MaskForeground(f) PIX_MASK_DRAW -#else +#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ + #define MaskForeground(f) WHITE_PIX_DEFAULT (f) -#endif gc = XCreateGC (dpy, img->pixmap, 0, NULL); XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f)); @@ -5354,6 +4887,7 @@ x_disable_image (f, img) img->width - 1, 0); XFreeGC (dpy, gc); } +#endif /* !HAVE_NS */ #else HDC hdc, bmpdc; HGDIOBJ prev; @@ -5419,11 +4953,13 @@ x_build_heuristic_mask (f, img, how) } #ifndef HAVE_NTGUI +#ifndef HAVE_NS /* Create an image and pixmap serving as mask. */ rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, &mask_img, &img->mask); if (!rc) return 0; +#endif /* !HAVE_NS */ /* Get the X image of IMG->pixmap. */ ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0, @@ -5477,16 +5013,21 @@ x_build_heuristic_mask (f, img, how) #ifndef HAVE_NTGUI for (y = 0; y < img->height; ++y) for (x = 0; x < img->width; ++x) +#ifndef HAVE_NS XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW : PIX_MASK_RETAIN)); - +#else + if (XGetPixel (ximg, x, y) == bg) + ns_set_alpha(ximg, x, y, 0); +#endif /* HAVE_NS */ +#ifndef HAVE_NS /* Fill in the background_transparent field while we have the mask handy. */ image_background_transparent (img, f, mask_img); /* Put mask_img into img->mask. */ x_put_x_image (f, mask_img, img->mask, img->width, img->height); x_destroy_x_image (mask_img); - +#endif /* !HAVE_NS */ #else for (y = 0; y < img->height; ++y) for (x = 0; x < img->width; ++x) @@ -5546,7 +5087,7 @@ enum pbm_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword pbm_format[PBM_LAST] = +static const struct image_keyword pbm_format[PBM_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":file", IMAGE_STRING_VALUE, 0}, @@ -5768,13 +5309,18 @@ pbm_load (f, img) if (type != PBM_MONO) { max_color_idx = pbm_scan_number (&p, end); - if (raw_p && max_color_idx > 255) - max_color_idx = 255; + if (max_color_idx > 65535 || max_color_idx < 0) + { + image_error ("Unsupported maximum PBM color value", Qnil, Qnil); + goto error; + } } - if (!check_image_size (f, width, height) - || (type != PBM_MONO && max_color_idx < 0)) - goto error; + if (!check_image_size (f, width, height)) + { + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + goto error; + } if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) @@ -5834,10 +5380,13 @@ pbm_load (f, img) } else { - if (raw_p - && ((type == PBM_GRAY) - ? (p + height * width > end) - : (p + 3 * height * width > end))) + int expected_size = height * width; + if (max_color_idx > 255) + expected_size *= 2; + if (type == PBM_COLOR) + expected_size *= 3; + + if (raw_p && p + expected_size > end) { x_destroy_x_image (ximg); x_clear_image (f, img); @@ -5851,13 +5400,25 @@ pbm_load (f, img) { int r, g, b; - if (type == PBM_GRAY) - r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end); + if (type == PBM_GRAY && raw_p) + { + r = g = b = *p++; + if (max_color_idx > 255) + r = g = b = r * 256 + *p++; + } + else if (type == PBM_GRAY) + r = g = b = pbm_scan_number (&p, end); else if (raw_p) { r = *p++; + if (max_color_idx > 255) + r = r * 256 + *p++; g = *p++; + if (max_color_idx > 255) + g = g * 256 + *p++; b = *p++; + if (max_color_idx > 255) + b = b * 256 + *p++; } else { @@ -5917,7 +5478,7 @@ pbm_load (f, img) PNG ***********************************************************************/ -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (HAVE_NS) /* Function prototypes. */ @@ -5948,7 +5509,7 @@ enum png_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword png_format[PNG_LAST] = +static const struct image_keyword png_format[PNG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, @@ -5989,22 +5550,16 @@ png_image_p (object) return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; } -#endif /* HAVE_PNG || MAC_OS */ +#endif /* HAVE_PNG || HAVE_NS */ #ifdef HAVE_PNG -#if defined HAVE_LIBPNG_PNG_H -# include -#else -# include -#endif - #ifdef HAVE_NTGUI /* PNG library details. */ DEF_IMGLIB_FN (png_get_io_ptr); -DEF_IMGLIB_FN (png_check_sig); +DEF_IMGLIB_FN (png_sig_cmp); DEF_IMGLIB_FN (png_create_read_struct); DEF_IMGLIB_FN (png_create_info_struct); DEF_IMGLIB_FN (png_destroy_read_struct); @@ -6035,7 +5590,7 @@ init_png_functions (Lisp_Object libraries) return 0; LOAD_IMGLIB_FN (library, png_get_io_ptr); - LOAD_IMGLIB_FN (library, png_check_sig); + LOAD_IMGLIB_FN (library, png_sig_cmp); LOAD_IMGLIB_FN (library, png_create_read_struct); LOAD_IMGLIB_FN (library, png_create_info_struct); LOAD_IMGLIB_FN (library, png_destroy_read_struct); @@ -6060,7 +5615,7 @@ init_png_functions (Lisp_Object libraries) #else #define fn_png_get_io_ptr png_get_io_ptr -#define fn_png_check_sig png_check_sig +#define fn_png_sig_cmp png_sig_cmp #define fn_png_create_read_struct png_create_read_struct #define fn_png_create_info_struct png_create_info_struct #define fn_png_destroy_read_struct png_destroy_read_struct @@ -6178,7 +5733,6 @@ png_load (f, img) png_byte channels; png_uint_32 row_bytes; int transparent_p; - double screen_gamma; struct png_memory_storage tbr; /* Data to be read */ /* Find out what file to load. */ @@ -6208,7 +5762,7 @@ png_load (f, img) /* Check PNG signature. */ if (fread (sig, 1, sizeof sig, fp) != sizeof sig - || !fn_png_check_sig (sig, sizeof sig)) + || fn_png_sig_cmp (sig, 0, sizeof sig)) { image_error ("Not a PNG file: `%s'", file, Qnil); UNGCPRO; @@ -6225,7 +5779,7 @@ png_load (f, img) /* Check PNG signature. */ if (tbr.len < sizeof sig - || !fn_png_check_sig (tbr.bytes, sizeof sig)) + || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig)) { image_error ("Not a PNG image: `%s'", img->spec, Qnil); UNGCPRO; @@ -6294,8 +5848,10 @@ png_load (f, img) &interlace_type, NULL, NULL); if (!check_image_size (f, width, height)) - goto error; - + { + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + goto error; + } /* If image contains simply transparency data, we prefer to construct a clipping mask. */ if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) @@ -6320,27 +5876,6 @@ png_load (f, img) || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) fn_png_set_gray_to_rgb (png_ptr); - screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2); - -#if 0 /* Avoid double gamma correction for PNG images. */ - { /* Tell the PNG lib to handle gamma correction for us. */ - int intent; - double image_gamma; -#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED) - if (png_get_sRGB (png_ptr, info_ptr, &intent)) - /* The libpng documentation says this is right in this case. */ - png_set_gamma (png_ptr, screen_gamma, 0.45455); - else -#endif - if (png_get_gAMA (png_ptr, info_ptr, &image_gamma)) - /* Image contains gamma information. */ - png_set_gamma (png_ptr, screen_gamma, image_gamma); - else - /* Use the standard default for the image gamma. */ - png_set_gamma (png_ptr, screen_gamma, 0.45455); - } -#endif /* if 0 */ - /* Handle alpha channel by combining the image with a background color. Do this only if a real alpha channel is supplied. For simple transparency, we prefer a clipping mask. */ @@ -6349,39 +5884,30 @@ png_load (f, img) /* png_color_16 *image_bg; */ Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); + int shift = (bit_depth == 16) ? 0 : 8; if (STRINGP (specified_bg)) /* The user specified `:background', use that. */ { - /* W32 version incorrectly used COLORREF here!! ++kfs */ XColor color; if (x_defined_color (f, SDATA (specified_bg), &color, 0)) { png_color_16 user_bg; bzero (&user_bg, sizeof user_bg); - user_bg.red = color.red >> 8; - user_bg.green = color.green >> 8; - user_bg.blue = color.blue >> 8; + user_bg.red = color.red >> shift; + user_bg.green = color.green >> shift; + user_bg.blue = color.blue >> shift; fn_png_set_background (png_ptr, &user_bg, 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)) - 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 - to combine the image data via an alpha channel. Use - the frame's background instead. */ -#ifdef HAVE_X_WINDOWS + /* We use the current frame background, ignoring any default + background color set by the image. */ +#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) XColor color; png_color_16 frame_background; @@ -6389,37 +5915,11 @@ png_load (f, img) x_query_color (f, &color); bzero (&frame_background, sizeof frame_background); - frame_background.red = color.red >> 8; - frame_background.green = color.green >> 8; - frame_background.blue = color.blue >> 8; + frame_background.red = color.red >> shift; + frame_background.green = color.green >> shift; + frame_background.blue = color.blue >> shift; #endif /* HAVE_X_WINDOWS */ -#ifdef HAVE_NTGUI - COLORREF color; - png_color_16 frame_background; - color = FRAME_BACKGROUND_PIXEL (f); -#if 0 /* W32 TODO : Colormap support. */ - x_query_color (f, &color); -#endif - bzero (&frame_background, sizeof frame_background); - frame_background.red = GetRValue (color); - frame_background.green = GetGValue (color); - frame_background.blue = GetBValue (color); -#endif /* HAVE_NTGUI */ - -#ifdef MAC_OS - unsigned long color; - png_color_16 frame_background; - color = FRAME_BACKGROUND_PIXEL (f); -#if 0 /* MAC/W32 TODO : Colormap support. */ - x_query_color (f, &color); -#endif - bzero (&frame_background, sizeof frame_background); - frame_background.red = RED_FROM_ULONG (color); - frame_background.green = GREEN_FROM_ULONG (color); - frame_background.blue = BLUE_FROM_ULONG (color); -#endif /* MAC_OS */ - fn_png_set_background (png_ptr, &frame_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } @@ -6563,20 +6063,16 @@ png_load (f, img) #else /* HAVE_PNG */ -#ifdef MAC_OS +#ifdef HAVE_NS static int -png_load (f, img) - struct frame *f; - struct image *img; +png_load (struct frame *f, struct image *img) { -#ifdef MAC_OSX - if (MyCGImageCreateWithPNGDataProvider) - return image_load_quartz2d (f, img, 1); - else -#endif - return image_load_quicktime (f, img, kQTFileTypePNG); + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); } -#endif /* MAC_OS */ +#endif /* HAVE_NS */ + #endif /* !HAVE_PNG */ @@ -6586,7 +6082,7 @@ png_load (f, img) JPEG ***********************************************************************/ -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (HAVE_NS) static int jpeg_image_p P_ ((Lisp_Object object)); static int jpeg_load P_ ((struct frame *f, struct image *img)); @@ -6615,7 +6111,7 @@ enum jpeg_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword jpeg_format[JPEG_LAST] = +static const struct image_keyword jpeg_format[JPEG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, @@ -6657,7 +6153,7 @@ jpeg_image_p (object) return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1; } -#endif /* HAVE_JPEG || MAC_OS */ +#endif /* HAVE_JPEG || HAVE_NS */ #ifdef HAVE_JPEG @@ -6676,7 +6172,6 @@ jpeg_image_p (object) #include #include -#include #ifdef HAVE_STLIB_H_1 #define HAVE_STDLIB_H 1 @@ -7062,7 +6557,7 @@ jpeg_load (f, img) if (!check_image_size (f, width, height)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); longjmp (mgr.setjmp_buffer, 2); } @@ -7141,19 +6636,15 @@ jpeg_load (f, img) #else /* HAVE_JPEG */ -#ifdef MAC_OS +#ifdef HAVE_NS static int -jpeg_load (f, img) - struct frame *f; - struct image *img; +jpeg_load (struct frame *f, struct image *img) { -#ifdef MAC_OSX - return image_load_quartz2d (f, img, 0); -#else - return image_load_quicktime (f, img, kQTFileTypeJPEG); -#endif + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); } -#endif /* MAC_OS */ +#endif /* HAVE_NS */ #endif /* !HAVE_JPEG */ @@ -7163,7 +6654,7 @@ jpeg_load (f, img) TIFF ***********************************************************************/ -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (HAVE_NS) static int tiff_image_p P_ ((Lisp_Object object)); static int tiff_load P_ ((struct frame *f, struct image *img)); @@ -7186,13 +6677,14 @@ enum tiff_keyword_index TIFF_HEURISTIC_MASK, TIFF_MASK, TIFF_BACKGROUND, + TIFF_INDEX, TIFF_LAST }; /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword tiff_format[TIFF_LAST] = +static const struct image_keyword tiff_format[TIFF_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, @@ -7203,7 +6695,8 @@ static struct image_keyword tiff_format[TIFF_LAST] = {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":background", IMAGE_STRING_OR_NIL_VALUE, 0} + {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, + {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} }; /* Structure describing the image type `tiff'. */ @@ -7233,7 +6726,7 @@ tiff_image_p (object) return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1; } -#endif /* HAVE_TIFF || MAC_OS */ +#endif /* HAVE_TIFF || HAVE_NS */ #ifdef HAVE_TIFF @@ -7249,6 +6742,7 @@ DEF_IMGLIB_FN (TIFFClientOpen); DEF_IMGLIB_FN (TIFFGetField); DEF_IMGLIB_FN (TIFFReadRGBAImage); DEF_IMGLIB_FN (TIFFClose); +DEF_IMGLIB_FN (TIFFSetDirectory); static int init_tiff_functions (Lisp_Object libraries) @@ -7265,6 +6759,7 @@ init_tiff_functions (Lisp_Object libraries) LOAD_IMGLIB_FN (library, TIFFGetField); LOAD_IMGLIB_FN (library, TIFFReadRGBAImage); LOAD_IMGLIB_FN (library, TIFFClose); + LOAD_IMGLIB_FN (library, TIFFSetDirectory); return 1; } @@ -7277,7 +6772,7 @@ init_tiff_functions (Lisp_Object libraries) #define fn_TIFFGetField TIFFGetField #define fn_TIFFReadRGBAImage TIFFReadRGBAImage #define fn_TIFFClose TIFFClose - +#define fn_TIFFSetDirectory TIFFSetDirectory #endif /* HAVE_NTGUI */ @@ -7430,12 +6925,13 @@ tiff_load (f, img) Lisp_Object file, specified_file; Lisp_Object specified_data; TIFF *tiff; - int width, height, x, y; + int width, height, x, y, count; uint32 *buf; - int rc; + int rc, rc2; XImagePtr ximg; struct gcpro gcpro1; tiff_memory_source memsrc; + Lisp_Object image; specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); @@ -7491,6 +6987,20 @@ tiff_load (f, img) } } + image = image_spec_value (img->spec, QCindex, NULL); + if (INTEGERP (image)) + { + int ino = XFASTINT (image); + if (!fn_TIFFSetDirectory (tiff, ino)) + { + image_error ("Invalid image number `%s' in image `%s'", + image, img->spec); + fn_TIFFClose (tiff); + UNGCPRO; + return 0; + } + } + /* Get width and height of the image, and allocate a raster buffer of width x height 32-bit values. */ fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); @@ -7498,7 +7008,8 @@ tiff_load (f, img) if (!check_image_size (f, width, height)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + fn_TIFFClose (tiff); UNGCPRO; return 0; } @@ -7506,6 +7017,16 @@ tiff_load (f, img) buf = (uint32 *) xmalloc (width * height * sizeof *buf); rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); + + /* Count the number of images in the file. */ + for (count = 1, rc2 = 1; rc2; count++) + rc2 = fn_TIFFSetDirectory (tiff, count); + + if (count > 1) + img->data.lisp_val = Fcons (Qcount, + Fcons (make_number (count), + img->data.lisp_val)); + fn_TIFFClose (tiff); if (!rc) { @@ -7566,15 +7087,15 @@ tiff_load (f, img) #else /* HAVE_TIFF */ -#ifdef MAC_OS +#ifdef HAVE_NS static int -tiff_load (f, img) - struct frame *f; - struct image *img; +tiff_load (struct frame *f, struct image *img) { - return image_load_quicktime (f, img, kQTFileTypeTIFF); + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); } -#endif /* MAC_OS */ +#endif /* HAVE_NS */ #endif /* !HAVE_TIFF */ @@ -7584,7 +7105,7 @@ tiff_load (f, img) GIF ***********************************************************************/ -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (HAVE_NS) static int gif_image_p P_ ((Lisp_Object object)); static int gif_load P_ ((struct frame *f, struct image *img)); @@ -7615,7 +7136,7 @@ enum gif_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword gif_format[GIF_LAST] = +static const struct image_keyword gif_format[GIF_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, @@ -7626,7 +7147,7 @@ static struct image_keyword gif_format[GIF_LAST] = {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; @@ -7648,7 +7169,7 @@ gif_clear_image (f, img) struct frame *f; struct image *img; { - /* IMG->data.ptr_val may contain extension data. */ + /* IMG->data.ptr_val may contain metadata with extension data. */ img->data.lisp_val = Qnil; x_clear_image (f, img); } @@ -7669,11 +7190,11 @@ gif_image_p (object) return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1; } -#endif /* HAVE_GIF || MAC_OS */ +#endif /* HAVE_GIF */ #ifdef HAVE_GIF -#if defined (HAVE_NTGUI) || defined (MAC_OS) +#if defined (HAVE_NTGUI) /* winuser.h might define DrawText to DrawTextA or DrawTextW. Undefine before redefining to avoid a preprocessor warning. */ #ifdef DrawText @@ -7684,11 +7205,11 @@ gif_image_p (object) #include #undef DrawText -#else /* HAVE_NTGUI || MAC_OS */ +#else /* HAVE_NTGUI */ #include -#endif /* HAVE_NTGUI || MAC_OS */ +#endif /* HAVE_NTGUI */ #ifdef HAVE_NTGUI @@ -7759,8 +7280,8 @@ gif_read_from_memory (file, buf, len) /* Load GIF image IMG for use on frame F. Value is non-zero if successful. */ -static int interlace_start[] = {0, 4, 2, 1}; -static int interlace_increment[] = {8, 8, 4, 2}; +static const int interlace_start[] = {0, 4, 2, 1}; +static const int interlace_increment[] = {8, 8, 4, 2}; static int gif_load (f, img) @@ -7826,7 +7347,7 @@ gif_load (f, img) /* Before reading entire contents, check the declared image size. */ if (!check_image_size (f, gif->SWidth, gif->SHeight)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); fn_DGifCloseFile (gif); UNGCPRO; return 0; @@ -7869,7 +7390,7 @@ gif_load (f, img) if (!check_image_size (f, width, height)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); fn_DGifCloseFile (gif); UNGCPRO; return 0; @@ -7967,8 +7488,8 @@ gif_load (f, img) } } - /* Save GIF image extension data for `image-extension-data'. - Format is (count IMAGES FUNCTION "BYTES" ...). */ + /* Save GIF image extension data for `image-metadata'. + Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)). */ img->data.lisp_val = Qnil; if (gif->SavedImages[ino].ExtensionBlockCount > 0) { @@ -7978,7 +7499,9 @@ gif_load (f, img) img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount), Fcons (make_number (ext->Function), img->data.lisp_val)); - img->data.lisp_val = Fnreverse (img->data.lisp_val); + img->data.lisp_val = Fcons (Qextension_data, + Fcons (Fnreverse (img->data.lisp_val), + Qnil)); } if (gif->ImageCount > 1) img->data.lisp_val = Fcons (Qcount, @@ -8002,212 +7525,15 @@ gif_load (f, img) #else /* !HAVE_GIF */ -#ifdef MAC_OS +#ifdef HAVE_NS static int -gif_load (f, img) - struct frame *f; - struct image *img; +gif_load (struct frame *f, struct image *img) { - Lisp_Object specified_file, file; - Lisp_Object specified_data; - OSErr err; - Boolean graphic_p, movie_p, prefer_graphic_p; - Handle dh = NULL; - Movie movie = NULL; - Lisp_Object image; - Track track = NULL; - Media media = NULL; - long nsamples; - Rect rect; - Lisp_Object specified_bg; - XColor color; - RGBColor bg_color; - int width, height; - XImagePtr ximg; - 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 */ - FSSpec fss; - short refnum; - - err = find_image_fsspec (specified_file, &file, &fss); - if (err != noErr) - { - if (err == fnfErr) - image_error ("Cannot find image file `%s'", specified_file, Qnil); - else - goto open_error; - } - - err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0, - &graphic_p, &movie_p, &prefer_graphic_p, 0); - if (err != noErr) - goto open_error; - - if (!graphic_p && !movie_p) - goto open_error; - if (prefer_graphic_p) - return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL); - err = OpenMovieFile (&fss, &refnum, fsRdPerm); - if (err != noErr) - goto open_error; - err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL); - CloseMovieFile (refnum); - if (err != noErr) - { - image_error ("Error reading `%s'", file, Qnil); - return 0; - } - } - else - { - /* Memory source! */ - Handle dref = NULL; - long file_type_atom[3]; - - err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data)); - if (err != noErr) - { - image_error ("Cannot allocate data handle for `%s'", - img->spec, Qnil); - goto error; - } - - file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3); - file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType); - file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF); - err = PtrToHand (&dh, &dref, sizeof (Handle)); - if (err == noErr) - /* no file name */ - err = PtrAndHand ("\p", dref, 1); - if (err == noErr) - err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3); - if (err != noErr) - { - image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil); - goto error; - } - err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p, - &movie_p, &prefer_graphic_p, 0); - if (err != noErr) - goto open_error; - - if (!graphic_p && !movie_p) - goto open_error; - if (prefer_graphic_p) - { - int success_p; - - DisposeHandle (dref); - success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh); - DisposeHandle (dh); - return success_p; - } - err = NewMovieFromDataRef (&movie, 0, NULL, dref, - HandleDataHandlerSubType); - DisposeHandle (dref); - if (err != noErr) - goto open_error; - } - - image = image_spec_value (img->spec, QCindex, NULL); - ino = INTEGERP (image) ? XFASTINT (image) : 0; - track = GetMovieIndTrack (movie, 1); - media = GetTrackMedia (track); - nsamples = GetMediaSampleCount (media); - if (ino >= nsamples) - { - image_error ("Invalid image number `%s' in image `%s'", - image, img->spec); - goto error; - } - time_scale = GetMediaTimeScale (media); - - specified_bg = image_spec_value (img->spec, QCbackground, NULL); - if (!STRINGP (specified_bg) || - !mac_defined_color (f, SDATA (specified_bg), &color, 0)) - { - color.pixel = FRAME_BACKGROUND_PIXEL (f); - color.red = RED16_FROM_ULONG (color.pixel); - color.green = GREEN16_FROM_ULONG (color.pixel); - color.blue = BLUE16_FROM_ULONG (color.pixel); - } - GetMovieBox (movie, &rect); - width = img->width = rect.right - rect.left; - height = img->height = rect.bottom - rect.top; - if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) - goto error; - - GetGWorld (&old_port, &old_gdh); - SetGWorld (ximg, NULL); - bg_color.red = color.red; - bg_color.green = color.green; - bg_color.blue = color.blue; - RGBBackColor (&bg_color); - SetGWorld (old_port, old_gdh); - SetMovieActive (movie, 1); - SetMovieGWorld (movie, ximg, NULL); - SampleNumToMediaTime (media, ino + 1, &time, &duration); - SetMovieTimeValue (movie, time); - MoviesTask (movie, 0L); - DisposeTrackMedia (media); - DisposeMovieTrack (track); - 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); - - /* Put the image into the pixmap. */ - x_put_x_image (f, ximg, img->pixmap, width, height); - x_destroy_x_image (ximg); - return 1; - - open_error: - image_error ("Cannot open `%s'", file, Qnil); - error: - if (media) - DisposeTrackMedia (media); - if (track) - DisposeMovieTrack (track); - if (movie) - DisposeMovie (movie); - if (dh) - DisposeHandle (dh); - return 0; + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); } -#endif /* MAC_OS */ +#endif /* HAVE_NS */ #endif /* HAVE_GIF */ @@ -8251,7 +7577,7 @@ enum svg_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword svg_format[SVG_LAST] = +static const struct image_keyword svg_format[SVG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, @@ -8309,7 +7635,7 @@ svg_image_p (object) /* SVG library functions. */ DEF_IMGLIB_FN (rsvg_handle_new); -DEF_IMGLIB_FN (rsvg_handle_set_size_callback); +DEF_IMGLIB_FN (rsvg_handle_get_dimensions); DEF_IMGLIB_FN (rsvg_handle_write); DEF_IMGLIB_FN (rsvg_handle_close); DEF_IMGLIB_FN (rsvg_handle_get_pixbuf); @@ -8328,20 +7654,21 @@ DEF_IMGLIB_FN (g_type_init); DEF_IMGLIB_FN (g_object_unref); DEF_IMGLIB_FN (g_error_free); -Lisp_Object Qgdk_pixbuf, Qglib; +Lisp_Object Qgdk_pixbuf, Qglib, Qgobject; static int init_svg_functions (Lisp_Object libraries) { - HMODULE library, gdklib, glib; + HMODULE library, gdklib, glib, gobject; if (!(glib = w32_delayed_load (libraries, Qglib)) + || !(gobject = w32_delayed_load (libraries, Qgobject)) || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf)) || !(library = w32_delayed_load (libraries, Qsvg))) return 0; LOAD_IMGLIB_FN (library, rsvg_handle_new); - LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback); + LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions); LOAD_IMGLIB_FN (library, rsvg_handle_write); LOAD_IMGLIB_FN (library, rsvg_handle_close); LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf); @@ -8356,9 +7683,10 @@ init_svg_functions (Lisp_Object libraries) LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha); LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample); - LOAD_IMGLIB_FN (glib, g_type_init); - LOAD_IMGLIB_FN (glib, g_object_unref); + LOAD_IMGLIB_FN (gobject, g_type_init); + LOAD_IMGLIB_FN (gobject, g_object_unref); LOAD_IMGLIB_FN (glib, g_error_free); + return 1; } @@ -8366,7 +7694,7 @@ init_svg_functions (Lisp_Object libraries) /* The following aliases for library functions allow dynamic loading to be used on some platforms. */ #define fn_rsvg_handle_new rsvg_handle_new -#define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback +#define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions #define fn_rsvg_handle_write rsvg_handle_write #define fn_rsvg_handle_close rsvg_handle_close #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf @@ -8461,6 +7789,7 @@ svg_load_image (f, img, contents, size) unsigned int size; { RsvgHandle *rsvg_handle; + RsvgDimensionData dimension_data; GError *error = NULL; GdkPixbuf *pixbuf; int width; @@ -8477,27 +7806,34 @@ svg_load_image (f, img, contents, size) gnome type library functions. */ fn_g_type_init (); /* Make a handle to a new rsvg object. */ - rsvg_handle = fn_rsvg_handle_new (); + rsvg_handle = (RsvgHandle *) fn_rsvg_handle_new (); /* Parse the contents argument and fill in the rsvg_handle. */ fn_rsvg_handle_write (rsvg_handle, contents, size, &error); - if (error) - goto rsvg_error; + if (error) goto rsvg_error; /* The parsing is complete, rsvg_handle is ready to used, close it for further writes. */ fn_rsvg_handle_close (rsvg_handle, &error); - if (error) - goto rsvg_error; + if (error) goto rsvg_error; + + fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data); + if (! check_image_size (f, dimension_data.width, dimension_data.height)) + { + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); + goto rsvg_error; + } + /* We can now get a valid pixel buffer from the svg file, if all went ok. */ - pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle); - eassert (pixbuf); + pixbuf = (GdkPixbuf *) fn_rsvg_handle_get_pixbuf (rsvg_handle); + if (!pixbuf) goto rsvg_error; + fn_g_object_unref (rsvg_handle); /* Extract some meta data from the svg handle. */ width = fn_gdk_pixbuf_get_width (pixbuf); height = fn_gdk_pixbuf_get_height (pixbuf); - pixels = fn_gdk_pixbuf_get_pixels (pixbuf); + pixels = (const guint8 *) fn_gdk_pixbuf_get_pixels (pixbuf); rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf); /* Validate the svg meta data. */ @@ -8518,47 +7854,24 @@ svg_load_image (f, img, contents, size) /* Handle alpha channel by combining the image with a background color. */ specified_bg = image_spec_value (img->spec, QCbackground, NULL); - if (STRINGP (specified_bg) - && x_defined_color (f, SDATA (specified_bg), &background, 0)) - { - background.red >>= 8; - background.green >>= 8; - background.blue >>= 8; - } - else + if (!STRINGP (specified_bg) + || !x_defined_color (f, SDATA (specified_bg), &background, 0)) { -#ifdef HAVE_X_WINDOWS - background.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &background); - - /* SVG pixmaps specify transparency in the last byte, so right - shift 8 bits to get rid of it, since emacs doesn't support - transparency. */ - background.red >>= 8; - background.green >>= 8; - background.blue >>= 8; -#elif defined (MAC_OS) +#ifndef HAVE_NS background.pixel = FRAME_BACKGROUND_PIXEL (f); - background.red = RED_FROM_ULONG (background.pixel); - background.green = GREEN_FROM_ULONG (background.pixel); - background.blue = BLUE_FROM_ULONG (background.pixel); -#elif defined (HAVE_NTGUI) - background.pixel = FRAME_BACKGROUND_PIXEL (f); -#if 0 /* W32 TODO : Colormap support. */ x_query_color (f, &background); -#endif - - /* SVG pixmaps specify transparency in the last byte, so right - shift 8 bits to get rid of it, since emacs doesn't support - transparency. */ - background.red >>= 8; - background.green >>= 8; - background.blue >>= 8; -#else /* not HAVE_X_WINDOWS && not MAC_OS*/ -#error FIXME +#else + ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1); #endif } + /* SVG pixmaps specify transparency in the last byte, so right + shift 8 bits to get rid of it, since emacs doesn't support + transparency. */ + background.red >>= 8; + background.green >>= 8; + background.blue >>= 8; + /* This loop handles opacity values, since Emacs assumes non-transparent images. Each pixel must be "flattened" by calculating the resulting color, given the transparency of the @@ -8613,6 +7926,7 @@ svg_load_image (f, img, contents, size) return 1; rsvg_error: + fn_g_object_unref (rsvg_handle); /* FIXME: Use error->message so the user knows what is the actual problem with the image. */ image_error ("Error parsing SVG image `%s'", img->spec, Qnil); @@ -8670,7 +7984,7 @@ enum gs_keyword_index /* Vector of image_keyword structures describing the format of valid user-defined image specifications. */ -static struct image_keyword gs_format[GS_LAST] = +static const struct image_keyword gs_format[GS_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1}, @@ -8781,7 +8095,7 @@ gs_load (f, img) if (!check_image_size (f, img->width, img->height)) { - image_error ("Invalid image size", Qnil, Qnil); + image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); return 0; } @@ -8841,7 +8155,7 @@ x_kill_gs_process (pixmap, f) Pixmap pixmap; struct frame *f; { - struct image_cache *c = FRAME_X_IMAGE_CACHE (f); + struct image_cache *c = FRAME_IMAGE_CACHE (f); int class, i; struct image *img; @@ -8991,27 +8305,27 @@ of `image-library-alist', which see). */) if (CONSP (tested)) return XCDR (tested); -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (HAVE_NS) if (EQ (type, Qxpm)) return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries); #endif -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (HAVE_NS) if (EQ (type, Qjpeg)) return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries); #endif -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (HAVE_NS) if (EQ (type, Qtiff)) return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries); #endif -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (HAVE_NS) if (EQ (type, Qgif)) return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries); #endif -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (HAVE_NS) if (EQ (type, Qpng)) return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries); #endif @@ -9061,7 +8375,7 @@ 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 are always supported. */); Vimage_library_alist = Qnil; - Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt); + Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt); DEFVAR_LISP ("max-image-size", &Vmax_image_size, doc: /* Maximum size of images. @@ -9078,103 +8392,108 @@ non-numeric, there is no explicit limit on the size of images. */); Vimage_type_cache = Qnil; staticpro (&Vimage_type_cache); - Qpbm = intern ("pbm"); + Qpbm = intern_c_string ("pbm"); staticpro (&Qpbm); ADD_IMAGE_TYPE (Qpbm); - Qxbm = intern ("xbm"); + Qxbm = intern_c_string ("xbm"); staticpro (&Qxbm); ADD_IMAGE_TYPE (Qxbm); define_image_type (&xbm_type, 1); define_image_type (&pbm_type, 1); - Qcount = intern ("count"); + Qcount = intern_c_string ("count"); staticpro (&Qcount); + Qextension_data = intern_c_string ("extension-data"); + staticpro (&Qextension_data); - QCascent = intern (":ascent"); + QCascent = intern_c_string (":ascent"); staticpro (&QCascent); - QCmargin = intern (":margin"); + QCmargin = intern_c_string (":margin"); staticpro (&QCmargin); - QCrelief = intern (":relief"); + QCrelief = intern_c_string (":relief"); staticpro (&QCrelief); - QCconversion = intern (":conversion"); + QCconversion = intern_c_string (":conversion"); staticpro (&QCconversion); - QCcolor_symbols = intern (":color-symbols"); + QCcolor_symbols = intern_c_string (":color-symbols"); staticpro (&QCcolor_symbols); - QCheuristic_mask = intern (":heuristic-mask"); + QCheuristic_mask = intern_c_string (":heuristic-mask"); staticpro (&QCheuristic_mask); - QCindex = intern (":index"); + QCindex = intern_c_string (":index"); staticpro (&QCindex); - QCmatrix = intern (":matrix"); + QCmatrix = intern_c_string (":matrix"); staticpro (&QCmatrix); - QCcolor_adjustment = intern (":color-adjustment"); + QCcolor_adjustment = intern_c_string (":color-adjustment"); staticpro (&QCcolor_adjustment); - QCmask = intern (":mask"); + QCmask = intern_c_string (":mask"); staticpro (&QCmask); - Qlaplace = intern ("laplace"); + Qlaplace = intern_c_string ("laplace"); staticpro (&Qlaplace); - Qemboss = intern ("emboss"); + Qemboss = intern_c_string ("emboss"); staticpro (&Qemboss); - Qedge_detection = intern ("edge-detection"); + Qedge_detection = intern_c_string ("edge-detection"); staticpro (&Qedge_detection); - Qheuristic = intern ("heuristic"); + Qheuristic = intern_c_string ("heuristic"); staticpro (&Qheuristic); - Qpostscript = intern ("postscript"); + Qpostscript = intern_c_string ("postscript"); staticpro (&Qpostscript); #ifdef HAVE_GHOSTSCRIPT ADD_IMAGE_TYPE (Qpostscript); - QCloader = intern (":loader"); + QCloader = intern_c_string (":loader"); staticpro (&QCloader); - QCbounding_box = intern (":bounding-box"); + QCbounding_box = intern_c_string (":bounding-box"); staticpro (&QCbounding_box); - QCpt_width = intern (":pt-width"); + QCpt_width = intern_c_string (":pt-width"); staticpro (&QCpt_width); - QCpt_height = intern (":pt-height"); + QCpt_height = intern_c_string (":pt-height"); staticpro (&QCpt_height); #endif /* HAVE_GHOSTSCRIPT */ -#if defined (HAVE_XPM) || defined (MAC_OS) - Qxpm = intern ("xpm"); +#if defined (HAVE_XPM) || defined (HAVE_NS) + Qxpm = intern_c_string ("xpm"); staticpro (&Qxpm); ADD_IMAGE_TYPE (Qxpm); #endif -#if defined (HAVE_JPEG) || defined (MAC_OS) - Qjpeg = intern ("jpeg"); +#if defined (HAVE_JPEG) || defined (HAVE_NS) + Qjpeg = intern_c_string ("jpeg"); staticpro (&Qjpeg); ADD_IMAGE_TYPE (Qjpeg); #endif -#if defined (HAVE_TIFF) || defined (MAC_OS) - Qtiff = intern ("tiff"); +#if defined (HAVE_TIFF) || defined (HAVE_NS) + Qtiff = intern_c_string ("tiff"); staticpro (&Qtiff); ADD_IMAGE_TYPE (Qtiff); #endif -#if defined (HAVE_GIF) || defined (MAC_OS) - Qgif = intern ("gif"); +#if defined (HAVE_GIF) || defined (HAVE_NS) + Qgif = intern_c_string ("gif"); staticpro (&Qgif); ADD_IMAGE_TYPE (Qgif); #endif -#if defined (HAVE_PNG) || defined (MAC_OS) - Qpng = intern ("png"); +#if defined (HAVE_PNG) || defined (HAVE_NS) + Qpng = intern_c_string ("png"); staticpro (&Qpng); ADD_IMAGE_TYPE (Qpng); #endif #if defined (HAVE_RSVG) - Qsvg = intern ("svg"); + Qsvg = intern_c_string ("svg"); staticpro (&Qsvg); ADD_IMAGE_TYPE (Qsvg); #ifdef HAVE_NTGUI - Qgdk_pixbuf = intern ("gdk-pixbuf"); + /* Other libraries used directly by svg code. */ + Qgdk_pixbuf = intern_c_string ("gdk-pixbuf"); staticpro (&Qgdk_pixbuf); - Qglib = intern ("glib"); + Qglib = intern_c_string ("glib"); staticpro (&Qglib); + Qgobject = intern_c_string ("gobject"); + staticpro (&Qgobject); #endif /* HAVE_NTGUI */ #endif /* HAVE_RSVG */ @@ -9183,7 +8502,7 @@ non-numeric, there is no explicit limit on the size of images. */); defsubr (&Simage_refresh); defsubr (&Simage_size); defsubr (&Simage_mask_p); - defsubr (&Simage_extension_data); + defsubr (&Simage_metadata); #if GLYPH_DEBUG defsubr (&Simagep); @@ -9211,9 +8530,6 @@ meaning don't clear the cache. */); void init_image () { -#if defined (MAC_OSX) && TARGET_API_MAC_CARBON - init_image_func_pointer (); -#endif } /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9