X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/093571c374d671607c822dd2e5bedb2ac877ea91..da39107c7b70daf7dc0a160936bdb565bbc36918:/src/image.c diff --git a/src/image.c b/src/image.c index 04fda4f88a..7ce5b9b2e0 100644 --- a/src/image.c +++ b/src/image.c @@ -5,10 +5,10 @@ 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 @@ -40,9 +38,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" @@ -82,49 +81,30 @@ typedef struct w32_bitmap_record Bitmap_Record; #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits) #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. */ @@ -166,6 +146,7 @@ XGetImage (display, pixmap, x, y, width, height, plane_mask, format) unsigned long plane_mask; /* not used */ int format; /* not used */ { +#if !USE_MAC_IMAGE_IO #if GLYPH_DEBUG xassert (x == 0 && y == 0); { @@ -177,6 +158,7 @@ XGetImage (display, pixmap, x, y, width, height, plane_mask, format) #endif LockPixels (GetGWorldPixMap (pixmap)); +#endif return pixmap; } @@ -187,6 +169,12 @@ XPutPixel (ximage, x, y, pixel) int x, y; unsigned long pixel; { +#if USE_MAC_IMAGE_IO + if (ximage->bits_per_pixel == 32) + ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel; + else + ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel; +#else PixMapHandle pixmap = GetGWorldPixMap (ximage); short depth = GetPixDepth (pixmap); @@ -227,6 +215,7 @@ XPutPixel (ximage, x, y, pixel) SetGWorld (old_port, old_gdh); } +#endif } static unsigned long @@ -234,6 +223,12 @@ XGetPixel (ximage, x, y) XImagePtr ximage; int x, y; { +#if USE_MAC_IMAGE_IO + if (ximage->bits_per_pixel == 32) + return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x]; + else + return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x]; +#else PixMapHandle pixmap = GetGWorldPixMap (ximage); short depth = GetPixDepth (pixmap); @@ -271,21 +266,78 @@ XGetPixel (ximage, x, y) SetGWorld (old_port, old_gdh); return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8); } +#endif } static void XDestroyImage (ximg) XImagePtr ximg; { +#if !USE_MAC_IMAGE_IO UnlockPixels (GetGWorldPixMap (ximg)); +#endif } #if USE_CG_DRAWING +#if USE_MAC_IMAGE_IO +void +mac_data_provider_release_data (info, data, size) + void *info; + const void *data; + size_t size; +{ + xfree ((void *)data); +} +#endif + static CGImageRef mac_create_cg_image_from_image (f, img) struct frame *f; struct image *img; { +#if USE_MAC_IMAGE_IO + XImagePtr ximg = img->pixmap; + CGDataProviderRef provider; + CGImageRef result; + + if (img->mask) + { + int x, y; + unsigned long color, alpha; + + for (y = 0; y < ximg->height; y++) + for (x = 0; x < ximg->width; x++) + { + color = XGetPixel (ximg, x, y); + alpha = XGetPixel (img->mask, x, y); + XPutPixel (ximg, x, y, + ARGB_TO_ULONG (alpha, + RED_FROM_ULONG (color) + * alpha / PIX_MASK_DRAW, + GREEN_FROM_ULONG (color) + * alpha / PIX_MASK_DRAW, + BLUE_FROM_ULONG (color) + * alpha / PIX_MASK_DRAW)); + } + xfree (img->mask->data); + img->mask->data = NULL; + } + BLOCK_INPUT; + provider = CGDataProviderCreateWithData (NULL, ximg->data, + ximg->bytes_per_line * ximg->height, + mac_data_provider_release_data); + ximg->data = NULL; + result = CGImageCreate (ximg->width, ximg->height, 8, 32, + ximg->bytes_per_line, mac_cg_color_space_rgb, + ((img->mask ? kCGImageAlphaPremultipliedFirst + : kCGImageAlphaNoneSkipFirst) + | kCGBitmapByteOrder32Host), + provider, NULL, 0, kCGRenderingIntentDefault); + CGDataProviderRelease (provider); + UNBLOCK_INPUT; + + return result; +#else Pixmap mask; CGImageRef result = NULL; @@ -320,10 +372,38 @@ mac_create_cg_image_from_image (f, img) UNBLOCK_INPUT; return result; +#endif } #endif /* USE_CG_DRAWING */ #endif /* MAC_OS */ +#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) +{ + /* TODO: not sure what this function is supposed to do.. */ + ns_retain_object(pixmap); + return pixmap; +} + +/* use with imgs created by ns_image_for_XPM */ +unsigned long +XGetPixel (XImagePtr ximage, int x, int y) +{ + return ns_get_pixel(ximage, x, y); +} + +/* 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) +{ + ns_put_pixel(ximage, x, y, pixel); +} +#endif /* HAVE_NS */ + /* Functions to access the contents of a bitmap, given an id. */ @@ -434,17 +514,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 +554,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 +643,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) { @@ -1184,9 +1280,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 +1305,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 +1377,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 +1413,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 +1483,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 +1499,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 +1622,10 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p) { Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); img->pixmap = NO_PIXMAP; +#ifdef HAVE_NS + if (img->background_valid) + ns_free_indexed_color(img->background); +#endif img->background_valid = 0; } @@ -1538,7 +1638,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 +1647,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 +1734,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 +1781,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 +1794,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 +1829,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 +1849,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 +1860,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 +2016,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 +2127,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 +2162,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 +2376,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 +2409,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 +2443,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 } @@ -2429,367 +2529,6 @@ slurp_file (file, size) } - -#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); - - 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; - } - - 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); - } - } - - if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) - { - CGImageRelease (image); - UNGCPRO; - return 0; - } - rectangle = CGRectMake (0, 0, width, height); - QDBeginCGContext (ximg, &context); - if (png_p) - { - CGContextSetRGBFillColor (context, color.red / 65535.0, - color.green / 65535.0, - color.blue / 65535.0, 1.0); - CGContextFillRect (context, rectangle); - } - 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; -} -#endif - -#endif /* MAC_OS */ - /*********************************************************************** XBM images @@ -3171,6 +2910,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), @@ -3179,7 +2922,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 */ } @@ -3563,13 +3306,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 @@ -3592,7 +3335,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; @@ -3919,7 +3662,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 @@ -4198,9 +3941,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 *, @@ -4257,8 +4000,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; @@ -4534,7 +4277,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)) @@ -4543,7 +4286,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); @@ -4556,8 +4299,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; @@ -4577,9 +4323,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 (','); @@ -4594,6 +4345,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 @@ -4609,7 +4361,7 @@ xpm_load_image (f, img, contents, end) Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); img->mask = NO_PIXMAP; } - +#endif return 1; failure: @@ -4675,7 +4427,7 @@ xpm_load (f, img) return success_p; } -#endif /* MAC_OS */ +#endif /* HAVE_NS && !HAVE_XPM */ @@ -4936,15 +4688,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; } @@ -5050,11 +4800,11 @@ x_to_xcolors (f, img, rgb_p) p->pixel = GET_PIXEL (ximg, x, y); if (rgb_p) { -#ifdef MAC_OS +#if defined (HAVE_NS) p->red = RED16_FROM_ULONG (p->pixel); p->green = GREEN16_FROM_ULONG (p->pixel); p->blue = BLUE16_FROM_ULONG (p->pixel); -#endif /* MAC_OS */ +#endif /* HAVE_NS */ #ifdef HAVE_NTGUI p->red = 256 * GetRValue (p->pixel); p->green = 256 * GetGValue (p->pixel); @@ -5131,7 +4881,7 @@ x_from_xcolors (f, img, colors) XColor *colors; { int x, y; - XImagePtr oimg; + XImagePtr oimg = NULL; Pixmap pixmap; XColor *p; @@ -5345,11 +5095,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)); @@ -5369,6 +5117,7 @@ x_disable_image (f, img) img->width - 1, 0); XFreeGC (dpy, gc); } +#endif /* !HAVE_NS */ #else HDC hdc, bmpdc; HGDIOBJ prev; @@ -5434,11 +5183,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, @@ -5492,16 +5243,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) @@ -5783,13 +5539,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", Qnil, Qnil); + goto error; + } if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) @@ -5849,10 +5610,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); @@ -5866,13 +5630,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 { @@ -5932,7 +5708,7 @@ pbm_load (f, img) PNG ***********************************************************************/ -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (HAVE_NS) /* Function prototypes. */ @@ -6004,7 +5780,7 @@ 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 @@ -6193,7 +5969,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. */ @@ -6335,27 +6110,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. */ @@ -6364,6 +6118,7 @@ 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. */ @@ -6375,27 +6130,18 @@ png_load (f, img) 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. */ + /* We use the current frame background, ignoring any default + background color set by the image. */ #ifdef HAVE_X_WINDOWS XColor color; png_color_16 frame_background; @@ -6404,9 +6150,9 @@ 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 @@ -6422,19 +6168,6 @@ png_load (f, img) 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); } @@ -6578,20 +6311,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 */ @@ -6601,7 +6330,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)); @@ -6672,7 +6401,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 @@ -7156,19 +6885,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 */ @@ -7178,7 +6903,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)); @@ -7201,6 +6926,7 @@ enum tiff_keyword_index TIFF_HEURISTIC_MASK, TIFF_MASK, TIFF_BACKGROUND, + TIFF_INDEX, TIFF_LAST }; @@ -7218,7 +6944,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'. */ @@ -7248,7 +6975,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 @@ -7264,6 +6991,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) @@ -7280,6 +7008,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; } @@ -7292,7 +7021,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 */ @@ -7445,12 +7174,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); @@ -7506,6 +7236,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); @@ -7514,6 +7258,7 @@ tiff_load (f, img) if (!check_image_size (f, width, height)) { image_error ("Invalid image size", Qnil, Qnil); + fn_TIFFClose (tiff); UNGCPRO; return 0; } @@ -7521,6 +7266,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) { @@ -7581,15 +7336,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 */ @@ -7599,7 +7354,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)); @@ -7641,7 +7396,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} }; @@ -7684,11 +7439,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 @@ -7699,11 +7454,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 @@ -8017,212 +7772,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 */ @@ -8324,7 +7882,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); @@ -8356,7 +7914,7 @@ init_svg_functions (Lisp_Object libraries) 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); @@ -8381,7 +7939,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 @@ -8476,6 +8034,7 @@ svg_load_image (f, img, contents, size) unsigned int size; { RsvgHandle *rsvg_handle; + RsvgDimensionData dimension_data; GError *error = NULL; GdkPixbuf *pixbuf; int width; @@ -8496,18 +8055,22 @@ svg_load_image (f, img, contents, size) /* 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) + 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)) 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); + 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); @@ -8552,11 +8115,6 @@ svg_load_image (f, img, contents, size) background.red >>= 8; background.green >>= 8; background.blue >>= 8; -#elif defined (MAC_OS) - 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. */ @@ -8569,7 +8127,7 @@ svg_load_image (f, img, contents, size) background.red >>= 8; background.green >>= 8; background.blue >>= 8; -#else /* not HAVE_X_WINDOWS && not MAC_OS*/ +#else /* not HAVE_X_WINDOWS*/ #error FIXME #endif } @@ -8628,6 +8186,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); @@ -8856,7 +8415,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; @@ -9006,27 +8565,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 @@ -9151,31 +8710,31 @@ non-numeric, there is no explicit limit on the size of images. */); staticpro (&QCpt_height); #endif /* HAVE_GHOSTSCRIPT */ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (HAVE_NS) Qxpm = intern ("xpm"); staticpro (&Qxpm); ADD_IMAGE_TYPE (Qxpm); #endif -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (HAVE_NS) Qjpeg = intern ("jpeg"); staticpro (&Qjpeg); ADD_IMAGE_TYPE (Qjpeg); #endif -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (HAVE_NS) Qtiff = intern ("tiff"); staticpro (&Qtiff); ADD_IMAGE_TYPE (Qtiff); #endif -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (HAVE_NS) Qgif = intern ("gif"); staticpro (&Qgif); ADD_IMAGE_TYPE (Qgif); #endif -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (HAVE_NS) Qpng = intern ("png"); staticpro (&Qpng); ADD_IMAGE_TYPE (Qpng); @@ -9226,9 +8785,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