1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
39 #include "dispextern.h"
40 #include "blockinput.h"
49 #include <sys/types.h>
52 #define COLOR_TABLE_SUPPORT 1
54 typedef struct x_bitmap_record Bitmap_Record
;
55 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
56 #define NO_PIXMAP None
58 #define RGB_PIXEL_COLOR unsigned long
60 #define PIX_MASK_RETAIN 0
61 #define PIX_MASK_DRAW 1
62 #endif /* HAVE_X_WINDOWS */
68 /* W32_TODO : Color tables on W32. */
69 #undef COLOR_TABLE_SUPPORT
71 typedef struct w32_bitmap_record Bitmap_Record
;
72 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
75 #define RGB_PIXEL_COLOR COLORREF
77 #define PIX_MASK_RETAIN 0
78 #define PIX_MASK_DRAW 1
80 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
81 #define x_defined_color w32_defined_color
82 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 #endif /* HAVE_NTGUI */
91 #include <sys/param.h>
93 #if TARGET_API_MAC_CARBON
95 #include <QuickTime/QuickTime.h>
96 #else /* not MAC_OSX */
97 #include <QuickTime.h>
98 #endif /* not MAC_OSX */
99 #else /* not TARGET_API_MAC_CARBON */
102 #include <TextUtils.h>
103 #include <ImageCompression.h>
104 #include <QuickTimeComponents.h>
105 #endif /* not TARGET_API_MAC_CARBON */
107 /* MAC_TODO : Color tables on Mac. */
108 #undef COLOR_TABLE_SUPPORT
110 #define ZPixmap 0 /* arbitrary */
111 typedef struct mac_bitmap_record Bitmap_Record
;
113 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
116 #define RGB_PIXEL_COLOR unsigned long
118 /* A black pixel in a mask bitmap/pixmap means ``draw a source
119 pixel''. A white pixel means ``retain the current pixel''. */
120 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
121 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
123 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
124 #define x_defined_color mac_defined_color
125 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
130 /* Search path for bitmap files. */
132 Lisp_Object Vx_bitmap_file_path
;
135 static void x_disable_image
P_ ((struct frame
*, struct image
*));
136 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
139 static void init_color_table
P_ ((void));
140 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
141 #ifdef COLOR_TABLE_SUPPORT
142 static void free_color_table
P_ ((void));
143 static unsigned long *colors_in_color_table
P_ ((int *n
));
144 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
147 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
148 id, which is just an int that this section returns. Bitmaps are
149 reference counted so they can be shared among frames.
151 Bitmap indices are guaranteed to be > 0, so a negative number can
152 be used to indicate no bitmap.
154 If you use x_create_bitmap_from_data, then you must keep track of
155 the bitmaps yourself. That is, creating a bitmap from the same
156 data more than once will not be caught. */
161 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
162 Display
*display
; /* not used */
164 int x
, y
; /* not used */
165 unsigned int width
, height
; /* not used */
166 unsigned long plane_mask
; /* not used */
167 int format
; /* not used */
170 xassert (x
== 0 && y
== 0);
173 SetRect (&ri
, 0, 0, width
, height
);
174 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
176 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
179 LockPixels (GetGWorldPixMap (pixmap
));
185 XPutPixel (ximage
, x
, y
, pixel
)
190 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
191 short depth
= GetPixDepth (pixmap
);
193 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
196 char *base_addr
= GetPixBaseAddr (pixmap
);
197 short row_bytes
= GetPixRowBytes (pixmap
);
199 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
205 char *base_addr
= GetPixBaseAddr (pixmap
);
206 short row_bytes
= GetPixRowBytes (pixmap
);
208 if (pixel
== PIX_MASK_DRAW
)
209 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
211 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
219 GetGWorld (&old_port
, &old_gdh
);
220 SetGWorld (ximage
, NULL
);
222 color
.red
= RED16_FROM_ULONG (pixel
);
223 color
.green
= GREEN16_FROM_ULONG (pixel
);
224 color
.blue
= BLUE16_FROM_ULONG (pixel
);
226 SetCPixel (x
, y
, &color
);
228 SetGWorld (old_port
, old_gdh
);
233 XGetPixel (ximage
, x
, y
)
237 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
238 short depth
= GetPixDepth (pixmap
);
240 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
243 char *base_addr
= GetPixBaseAddr (pixmap
);
244 short row_bytes
= GetPixRowBytes (pixmap
);
246 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
252 char *base_addr
= GetPixBaseAddr (pixmap
);
253 short row_bytes
= GetPixRowBytes (pixmap
);
255 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
256 return PIX_MASK_DRAW
;
258 return PIX_MASK_RETAIN
;
266 GetGWorld (&old_port
, &old_gdh
);
267 SetGWorld (ximage
, NULL
);
269 GetCPixel (x
, y
, &color
);
271 SetGWorld (old_port
, old_gdh
);
272 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
280 UnlockPixels (GetGWorldPixMap (ximg
));
285 mac_create_cg_image_from_image (f
, img
)
290 CGImageRef result
= NULL
;
297 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
298 img
->width
, img
->height
, 1);
305 GetGWorld (&old_port
, &old_gdh
);
306 SetGWorld (mask
, NULL
);
307 BackColor (blackColor
); /* Don't mask. */
308 SetRect (&r
, 0, 0, img
->width
, img
->height
);
310 SetGWorld (old_port
, old_gdh
);
315 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
316 GetGWorldPixMap (mask
), &result
);
317 if (mask
!= img
->mask
)
318 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
324 #endif /* USE_CG_DRAWING */
328 /* Functions to access the contents of a bitmap, given an id. */
331 x_bitmap_height (f
, id
)
335 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
339 x_bitmap_width (f
, id
)
343 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
346 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
348 x_bitmap_pixmap (f
, id
)
352 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
356 #ifdef HAVE_X_WINDOWS
358 x_bitmap_mask (f
, id
)
362 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
366 /* Allocate a new bitmap record. Returns index of new record. */
369 x_allocate_bitmap_record (f
)
372 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
375 if (dpyinfo
->bitmaps
== NULL
)
377 dpyinfo
->bitmaps_size
= 10;
379 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
380 dpyinfo
->bitmaps_last
= 1;
384 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
385 return ++dpyinfo
->bitmaps_last
;
387 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
388 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
391 dpyinfo
->bitmaps_size
*= 2;
393 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
394 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
395 return ++dpyinfo
->bitmaps_last
;
398 /* Add one reference to the reference count of the bitmap with id ID. */
401 x_reference_bitmap (f
, id
)
405 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
408 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
411 x_create_bitmap_from_data (f
, bits
, width
, height
)
414 unsigned int width
, height
;
416 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
419 #ifdef HAVE_X_WINDOWS
421 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
422 bits
, width
, height
);
425 #endif /* HAVE_X_WINDOWS */
429 bitmap
= CreateBitmap (width
, height
,
430 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
431 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
435 #endif /* HAVE_NTGUI */
438 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
443 id
= x_allocate_bitmap_record (f
);
445 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
446 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
449 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
450 dpyinfo
->bitmaps
[id
- 1].height
= height
;
451 dpyinfo
->bitmaps
[id
- 1].width
= width
;
452 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
454 #ifdef HAVE_X_WINDOWS
455 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
456 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
457 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
458 #endif /* HAVE_X_WINDOWS */
461 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
462 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
463 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
464 #endif /* HAVE_NTGUI */
469 /* Create bitmap from file FILE for frame F. */
472 x_create_bitmap_from_file (f
, file
)
477 return -1; /* MAC_TODO : bitmap support */
481 return -1; /* W32_TODO : bitmap support */
482 #endif /* HAVE_NTGUI */
484 #ifdef HAVE_X_WINDOWS
485 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
486 unsigned int width
, height
;
488 int xhot
, yhot
, result
, id
;
493 /* Look for an existing bitmap with the same name. */
494 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
496 if (dpyinfo
->bitmaps
[id
].refcount
497 && dpyinfo
->bitmaps
[id
].file
498 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
500 ++dpyinfo
->bitmaps
[id
].refcount
;
505 /* Search bitmap-file-path for the file, if appropriate. */
506 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
511 filename
= (char *) SDATA (found
);
513 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
514 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
515 if (result
!= BitmapSuccess
)
518 id
= x_allocate_bitmap_record (f
);
519 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
520 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
521 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
522 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
523 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
524 dpyinfo
->bitmaps
[id
- 1].height
= height
;
525 dpyinfo
->bitmaps
[id
- 1].width
= width
;
526 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
529 #endif /* HAVE_X_WINDOWS */
535 Free_Bitmap_Record (dpyinfo
, bm
)
536 Display_Info
*dpyinfo
;
539 #ifdef HAVE_X_WINDOWS
540 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
542 XFreePixmap (dpyinfo
->display
, bm
->mask
);
543 #endif /* HAVE_X_WINDOWS */
546 DeleteObject (bm
->pixmap
);
547 #endif /* HAVE_NTGUI */
550 xfree (bm
->bitmap_data
); /* Added ++kfs */
551 bm
->bitmap_data
= NULL
;
561 /* Remove reference to bitmap with id number ID. */
564 x_destroy_bitmap (f
, id
)
568 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
572 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
574 if (--bm
->refcount
== 0)
577 Free_Bitmap_Record (dpyinfo
, bm
);
583 /* Free all the bitmaps for the display specified by DPYINFO. */
586 x_destroy_all_bitmaps (dpyinfo
)
587 Display_Info
*dpyinfo
;
590 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
592 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
593 if (bm
->refcount
> 0)
594 Free_Bitmap_Record (dpyinfo
, bm
);
596 dpyinfo
->bitmaps_last
= 0;
600 #ifdef HAVE_X_WINDOWS
602 /* Useful functions defined in the section
603 `Image type independent image structures' below. */
605 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
608 unsigned long height
));
610 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
611 int depth
, XImagePtr
*ximg
,
614 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
617 /* Create a mask of a bitmap. Note is this not a perfect mask.
618 It's nicer with some borders in this context */
621 x_create_bitmap_mask (f
, id
)
626 XImagePtr ximg
, mask_img
;
627 unsigned long width
, height
;
630 unsigned long x
, y
, xp
, xm
, yp
, ym
;
633 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
638 pixmap
= x_bitmap_pixmap (f
, id
);
639 width
= x_bitmap_width (f
, id
);
640 height
= x_bitmap_height (f
, id
);
643 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
652 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
657 XDestroyImage (ximg
);
661 bg
= four_corners_best (ximg
, NULL
, width
, height
);
663 for (y
= 0; y
< ximg
->height
; ++y
)
665 for (x
= 0; x
< ximg
->width
; ++x
)
667 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
668 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
669 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
670 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
671 if (XGetPixel (ximg
, x
, y
) == bg
672 && XGetPixel (ximg
, x
, yp
) == bg
673 && XGetPixel (ximg
, x
, ym
) == bg
674 && XGetPixel (ximg
, xp
, y
) == bg
675 && XGetPixel (ximg
, xp
, yp
) == bg
676 && XGetPixel (ximg
, xp
, ym
) == bg
677 && XGetPixel (ximg
, xm
, y
) == bg
678 && XGetPixel (ximg
, xm
, yp
) == bg
679 && XGetPixel (ximg
, xm
, ym
) == bg
)
680 XPutPixel (mask_img
, x
, y
, 0);
682 XPutPixel (mask_img
, x
, y
, 1);
686 xassert (interrupt_input_blocked
);
687 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
688 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
690 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
692 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
693 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
695 XDestroyImage (ximg
);
696 x_destroy_x_image (mask_img
);
701 #endif /* HAVE_X_WINDOWS */
704 /***********************************************************************
706 ***********************************************************************/
708 /* Value is the number of elements of vector VECTOR. */
710 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
712 /* List of supported image types. Use define_image_type to add new
713 types. Use lookup_image_type to find a type for a given symbol. */
715 static struct image_type
*image_types
;
717 /* A list of symbols, one for each supported image type. */
719 Lisp_Object Vimage_types
;
721 /* An alist of image types and libraries that implement the type. */
723 Lisp_Object Vimage_library_alist
;
725 /* Cache for delayed-loading image types. */
727 static Lisp_Object Vimage_type_cache
;
729 /* The symbol `xbm' which is used as the type symbol for XBM images. */
735 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
736 extern Lisp_Object QCdata
, QCtype
, Qcount
;
737 extern Lisp_Object Qcenter
;
738 Lisp_Object QCascent
, QCmargin
, QCrelief
;
739 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
740 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
744 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
746 /* Time in seconds after which images should be removed from the cache
749 Lisp_Object Vimage_cache_eviction_delay
;
751 /* Function prototypes. */
753 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
754 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
755 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
756 static void x_laplace
P_ ((struct frame
*, struct image
*));
757 static void x_emboss
P_ ((struct frame
*, struct image
*));
758 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
761 #define CACHE_IMAGE_TYPE(type, status) \
762 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
764 #define ADD_IMAGE_TYPE(type) \
765 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
767 /* Define a new image type from TYPE. This adds a copy of TYPE to
768 image_types and caches the loading status of TYPE. */
771 define_image_type (type
, loaded
)
772 struct image_type
*type
;
781 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
782 The initialized data segment is read-only. */
783 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
784 bcopy (type
, p
, sizeof *p
);
785 p
->next
= image_types
;
790 CACHE_IMAGE_TYPE (*type
->type
, success
);
795 /* Look up image type SYMBOL, and return a pointer to its image_type
796 structure. Value is null if SYMBOL is not a known image type. */
798 static INLINE
struct image_type
*
799 lookup_image_type (symbol
)
802 struct image_type
*type
;
804 /* We must initialize the image-type if it hasn't been already. */
805 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
806 return 0; /* unimplemented */
808 for (type
= image_types
; type
; type
= type
->next
)
809 if (EQ (symbol
, *type
->type
))
816 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
817 valid image specification is a list whose car is the symbol
818 `image', and whose rest is a property list. The property list must
819 contain a value for key `:type'. That value must be the name of a
820 supported image type. The rest of the property list depends on the
824 valid_image_p (object
)
833 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
834 if (EQ (XCAR (tem
), QCtype
))
837 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
839 struct image_type
*type
;
840 type
= lookup_image_type (XCAR (tem
));
842 valid_p
= type
->valid_p (object
);
853 /* Log error message with format string FORMAT and argument ARG.
854 Signaling an error, e.g. when an image cannot be loaded, is not a
855 good idea because this would interrupt redisplay, and the error
856 message display would lead to another redisplay. This function
857 therefore simply displays a message. */
860 image_error (format
, arg1
, arg2
)
862 Lisp_Object arg1
, arg2
;
864 add_to_log (format
, arg1
, arg2
);
869 /***********************************************************************
871 ***********************************************************************/
873 enum image_value_type
875 IMAGE_DONT_CHECK_VALUE_TYPE
,
877 IMAGE_STRING_OR_NIL_VALUE
,
879 IMAGE_POSITIVE_INTEGER_VALUE
,
880 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
881 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
884 IMAGE_FUNCTION_VALUE
,
889 /* Structure used when parsing image specifications. */
893 /* Name of keyword. */
896 /* The type of value allowed. */
897 enum image_value_type type
;
899 /* Non-zero means key must be present. */
902 /* Used to recognize duplicate keywords in a property list. */
905 /* The value that was found. */
910 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
912 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
915 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
916 has the format (image KEYWORD VALUE ...). One of the keyword/
917 value pairs must be `:type TYPE'. KEYWORDS is a vector of
918 image_keywords structures of size NKEYWORDS describing other
919 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
922 parse_image_spec (spec
, keywords
, nkeywords
, type
)
924 struct image_keyword
*keywords
;
935 while (CONSP (plist
))
937 Lisp_Object key
, value
;
939 /* First element of a pair must be a symbol. */
941 plist
= XCDR (plist
);
945 /* There must follow a value. */
948 value
= XCAR (plist
);
949 plist
= XCDR (plist
);
951 /* Find key in KEYWORDS. Error if not found. */
952 for (i
= 0; i
< nkeywords
; ++i
)
953 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
959 /* Record that we recognized the keyword. If a keywords
960 was found more than once, it's an error. */
961 keywords
[i
].value
= value
;
964 if (keywords
[i
].count
> 1)
967 /* Check type of value against allowed type. */
968 switch (keywords
[i
].type
)
970 case IMAGE_STRING_VALUE
:
971 if (!STRINGP (value
))
975 case IMAGE_STRING_OR_NIL_VALUE
:
976 if (!STRINGP (value
) && !NILP (value
))
980 case IMAGE_SYMBOL_VALUE
:
981 if (!SYMBOLP (value
))
985 case IMAGE_POSITIVE_INTEGER_VALUE
:
986 if (!INTEGERP (value
) || XINT (value
) <= 0)
990 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
991 if (INTEGERP (value
) && XINT (value
) >= 0)
994 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
995 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
999 case IMAGE_ASCENT_VALUE
:
1000 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1002 else if (INTEGERP (value
)
1003 && XINT (value
) >= 0
1004 && XINT (value
) <= 100)
1008 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1009 if (!INTEGERP (value
) || XINT (value
) < 0)
1013 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1016 case IMAGE_FUNCTION_VALUE
:
1017 value
= indirect_function (value
);
1019 || COMPILEDP (value
)
1020 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1024 case IMAGE_NUMBER_VALUE
:
1025 if (!INTEGERP (value
) && !FLOATP (value
))
1029 case IMAGE_INTEGER_VALUE
:
1030 if (!INTEGERP (value
))
1034 case IMAGE_BOOL_VALUE
:
1035 if (!NILP (value
) && !EQ (value
, Qt
))
1044 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1048 /* Check that all mandatory fields are present. */
1049 for (i
= 0; i
< nkeywords
; ++i
)
1050 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1053 return NILP (plist
);
1057 /* Return the value of KEY in image specification SPEC. Value is nil
1058 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1059 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1062 image_spec_value (spec
, key
, found
)
1063 Lisp_Object spec
, key
;
1068 xassert (valid_image_p (spec
));
1070 for (tail
= XCDR (spec
);
1071 CONSP (tail
) && CONSP (XCDR (tail
));
1072 tail
= XCDR (XCDR (tail
)))
1074 if (EQ (XCAR (tail
), key
))
1078 return XCAR (XCDR (tail
));
1088 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1089 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1090 PIXELS non-nil means return the size in pixels, otherwise return the
1091 size in canonical character units.
1092 FRAME is the frame on which the image will be displayed. FRAME nil
1093 or omitted means use the selected frame. */)
1094 (spec
, pixels
, frame
)
1095 Lisp_Object spec
, pixels
, frame
;
1100 if (valid_image_p (spec
))
1102 struct frame
*f
= check_x_frame (frame
);
1103 int id
= lookup_image (f
, spec
);
1104 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1105 int width
= img
->width
+ 2 * img
->hmargin
;
1106 int height
= img
->height
+ 2 * img
->vmargin
;
1109 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1110 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1112 size
= Fcons (make_number (width
), make_number (height
));
1115 error ("Invalid image specification");
1121 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1122 doc
: /* Return t if image SPEC has a mask bitmap.
1123 FRAME is the frame on which the image will be displayed. FRAME nil
1124 or omitted means use the selected frame. */)
1126 Lisp_Object spec
, frame
;
1131 if (valid_image_p (spec
))
1133 struct frame
*f
= check_x_frame (frame
);
1134 int id
= lookup_image (f
, spec
);
1135 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1140 error ("Invalid image specification");
1145 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1146 doc
: /* Return extension data for image SPEC.
1147 FRAME is the frame on which the image will be displayed. FRAME nil
1148 or omitted means use the selected frame. */)
1150 Lisp_Object spec
, frame
;
1155 if (valid_image_p (spec
))
1157 struct frame
*f
= check_x_frame (frame
);
1158 int id
= lookup_image (f
, spec
);
1159 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1160 ext
= img
->data
.lisp_val
;
1167 /***********************************************************************
1168 Image type independent image structures
1169 ***********************************************************************/
1171 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1172 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1173 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1175 #define MAX_IMAGE_SIZE 6.0
1176 Lisp_Object Vmax_image_size
;
1178 /* Allocate and return a new image structure for image specification
1179 SPEC. SPEC has a hash value of HASH. */
1181 static struct image
*
1182 make_image (spec
, hash
)
1186 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1188 xassert (valid_image_p (spec
));
1189 bzero (img
, sizeof *img
);
1190 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1191 xassert (img
->type
!= NULL
);
1193 img
->data
.lisp_val
= Qnil
;
1194 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1196 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1201 /* Free image IMG which was used on frame F, including its resources. */
1210 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1212 /* Remove IMG from the hash table of its cache. */
1214 img
->prev
->next
= img
->next
;
1216 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1219 img
->next
->prev
= img
->prev
;
1221 c
->images
[img
->id
] = NULL
;
1223 /* Free resources, then free IMG. */
1224 img
->type
->free (f
, img
);
1229 /* Return 1 if the given widths and heights are valid for display;
1230 otherwise, return 0. */
1233 check_image_size (f
, width
, height
)
1240 if (width
<= 0 || height
<= 0)
1243 if (INTEGERP (Vmax_image_size
))
1244 w
= h
= XINT (Vmax_image_size
);
1245 else if (FLOATP (Vmax_image_size
))
1249 w
= FRAME_PIXEL_WIDTH (f
);
1250 h
= FRAME_PIXEL_HEIGHT (f
);
1253 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1254 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1255 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1260 return (width
<= w
&& height
<= h
);
1263 /* Prepare image IMG for display on frame F. Must be called before
1264 drawing an image. */
1267 prepare_image_for_display (f
, img
)
1273 /* We're about to display IMG, so set its timestamp to `now'. */
1275 img
->timestamp
= EMACS_SECS (t
);
1277 /* If IMG doesn't have a pixmap yet, load it now, using the image
1278 type dependent loader function. */
1279 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1280 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1282 #if defined (MAC_OS) && USE_CG_DRAWING
1283 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1285 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1286 if (img
->data
.ptr_val
== NULL
)
1288 img
->load_failed_p
= 1;
1289 img
->type
->free (f
, img
);
1296 /* Value is the number of pixels for the ascent of image IMG when
1297 drawn in face FACE. */
1300 image_ascent (img
, face
, slice
)
1303 struct glyph_slice
*slice
;
1308 if (slice
->height
== img
->height
)
1309 height
= img
->height
+ img
->vmargin
;
1310 else if (slice
->y
== 0)
1311 height
= slice
->height
+ img
->vmargin
;
1313 height
= slice
->height
;
1315 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1320 /* W32 specific version. Why?. ++kfs */
1321 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1322 - FONT_BASE(face
->font
)) / 2;
1324 /* This expression is arranged so that if the image can't be
1325 exactly centered, it will be moved slightly up. This is
1326 because a typical font is `top-heavy' (due to the presence
1327 uppercase letters), so the image placement should err towards
1328 being top-heavy too. It also just generally looks better. */
1329 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1330 #endif /* HAVE_NTGUI */
1333 ascent
= height
/ 2;
1336 ascent
= (int) (height
* img
->ascent
/ 100.0);
1342 /* Image background colors. */
1344 /* Find the "best" corner color of a bitmap.
1345 On W32, XIMG is assumed to a device context with the bitmap selected. */
1347 static RGB_PIXEL_COLOR
1348 four_corners_best (ximg
, corners
, width
, height
)
1349 XImagePtr_or_DC ximg
;
1351 unsigned long width
, height
;
1353 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1356 if (corners
&& corners
[BOT_CORNER
] >= 0)
1358 /* Get the colors at the corner_pixels of ximg. */
1359 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1360 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1361 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1362 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1366 /* Get the colors at the corner_pixels of ximg. */
1367 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1368 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1369 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1370 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1372 /* Choose the most frequently found color as background. */
1373 for (i
= best_count
= 0; i
< 4; ++i
)
1377 for (j
= n
= 0; j
< 4; ++j
)
1378 if (corner_pixels
[i
] == corner_pixels
[j
])
1382 best
= corner_pixels
[i
], best_count
= n
;
1388 /* Portability macros */
1392 #define Destroy_Image(img_dc, prev) \
1393 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1395 #define Free_Pixmap(display, pixmap) \
1396 DeleteObject (pixmap)
1400 #define Destroy_Image(ximg, dummy) \
1401 XDestroyImage (ximg)
1403 #define Free_Pixmap(display, pixmap) \
1404 XFreePixmap (display, pixmap)
1406 #endif /* HAVE_NTGUI */
1409 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1410 it is guessed heuristically. If non-zero, XIMG is an existing
1411 XImage object (or device context with the image selected on W32) to
1412 use for the heuristic. */
1415 image_background (img
, f
, ximg
)
1418 XImagePtr_or_DC ximg
;
1420 if (! img
->background_valid
)
1421 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1423 int free_ximg
= !ximg
;
1426 #endif /* HAVE_NTGUI */
1431 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1432 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1434 HDC frame_dc
= get_frame_dc (f
);
1435 ximg
= CreateCompatibleDC (frame_dc
);
1436 release_frame_dc (f
, frame_dc
);
1437 prev
= SelectObject (ximg
, img
->pixmap
);
1438 #endif /* !HAVE_NTGUI */
1441 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1444 Destroy_Image (ximg
, prev
);
1446 img
->background_valid
= 1;
1449 return img
->background
;
1452 /* Return the `background_transparent' field of IMG. If IMG doesn't
1453 have one yet, it is guessed heuristically. If non-zero, MASK is an
1454 existing XImage object to use for the heuristic. */
1457 image_background_transparent (img
, f
, mask
)
1460 XImagePtr_or_DC mask
;
1462 if (! img
->background_transparent_valid
)
1463 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1467 int free_mask
= !mask
;
1470 #endif /* HAVE_NTGUI */
1475 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1476 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1478 HDC frame_dc
= get_frame_dc (f
);
1479 mask
= CreateCompatibleDC (frame_dc
);
1480 release_frame_dc (f
, frame_dc
);
1481 prev
= SelectObject (mask
, img
->mask
);
1482 #endif /* HAVE_NTGUI */
1485 img
->background_transparent
1486 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1489 Destroy_Image (mask
, prev
);
1492 img
->background_transparent
= 0;
1494 img
->background_transparent_valid
= 1;
1497 return img
->background_transparent
;
1501 /***********************************************************************
1502 Helper functions for X image types
1503 ***********************************************************************/
1505 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1507 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1508 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1510 Lisp_Object color_name
,
1511 unsigned long dflt
));
1514 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1515 free the pixmap if any. MASK_P non-zero means clear the mask
1516 pixmap if any. COLORS_P non-zero means free colors allocated for
1517 the image, if any. */
1520 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1523 int pixmap_p
, mask_p
, colors_p
;
1525 if (pixmap_p
&& img
->pixmap
)
1527 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1528 img
->pixmap
= NO_PIXMAP
;
1529 img
->background_valid
= 0;
1532 if (mask_p
&& img
->mask
)
1534 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1535 img
->mask
= NO_PIXMAP
;
1536 img
->background_transparent_valid
= 0;
1539 if (colors_p
&& img
->ncolors
)
1541 /* MAC_TODO: color table support. */
1542 /* W32_TODO: color table support. */
1543 #ifdef HAVE_X_WINDOWS
1544 x_free_colors (f
, img
->colors
, img
->ncolors
);
1545 #endif /* HAVE_X_WINDOWS */
1546 xfree (img
->colors
);
1551 #if defined (MAC_OS) && USE_CG_DRAWING
1552 if (img
->data
.ptr_val
)
1554 CGImageRelease (img
->data
.ptr_val
);
1555 img
->data
.ptr_val
= NULL
;
1560 /* Free X resources of image IMG which is used on frame F. */
1563 x_clear_image (f
, img
)
1568 x_clear_image_1 (f
, img
, 1, 1, 1);
1573 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1574 cannot be allocated, use DFLT. Add a newly allocated color to
1575 IMG->colors, so that it can be freed again. Value is the pixel
1578 static unsigned long
1579 x_alloc_image_color (f
, img
, color_name
, dflt
)
1582 Lisp_Object color_name
;
1586 unsigned long result
;
1588 xassert (STRINGP (color_name
));
1590 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1592 /* This isn't called frequently so we get away with simply
1593 reallocating the color vector to the needed size, here. */
1596 (unsigned long *) xrealloc (img
->colors
,
1597 img
->ncolors
* sizeof *img
->colors
);
1598 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1599 result
= color
.pixel
;
1609 /***********************************************************************
1611 ***********************************************************************/
1613 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1614 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1615 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1617 /* Return a new, initialized image cache that is allocated from the
1618 heap. Call free_image_cache to free an image cache. */
1620 struct image_cache
*
1623 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1626 bzero (c
, sizeof *c
);
1628 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1629 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1630 c
->buckets
= (struct image
**) xmalloc (size
);
1631 bzero (c
->buckets
, size
);
1636 /* Find an image matching SPEC in the cache, and return it. If no
1637 image is found, return NULL. */
1638 static struct image
*
1639 search_image_cache (f
, spec
, hash
)
1645 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1646 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1648 if (!c
) return NULL
;
1650 /* If the image spec does not specify a background color, the cached
1651 image must have the same background color as the current frame.
1652 The foreground color must also match, for the sake of monochrome
1655 In fact, we could ignore the foreground color matching condition
1656 for color images, or if the image spec specifies :foreground;
1657 similarly we could ignore the background color matching condition
1658 for formats that don't use transparency (such as jpeg), or if the
1659 image spec specifies :background. However, the extra memory
1660 usage is probably negligible in practice, so we don't bother. */
1662 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1663 if (img
->hash
== hash
1664 && !NILP (Fequal (img
->spec
, spec
))
1665 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1666 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1672 /* Search frame F for an image with spec SPEC, and free it. */
1675 uncache_image (f
, spec
)
1679 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1681 free_image (f
, img
);
1685 /* Free image cache of frame F. Be aware that X frames share images
1689 free_image_cache (f
)
1692 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1697 /* Cache should not be referenced by any frame when freed. */
1698 xassert (c
->refcount
== 0);
1700 for (i
= 0; i
< c
->used
; ++i
)
1701 free_image (f
, c
->images
[i
]);
1705 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1710 /* Clear image cache of frame F. FORCE_P non-zero means free all
1711 images. FORCE_P zero means clear only images that haven't been
1712 displayed for some time. Should be called from time to time to
1713 reduce the number of loaded images. If image-eviction-seconds is
1714 non-nil, this frees images in the cache which weren't displayed for
1715 at least that many seconds. */
1718 clear_image_cache (f
, force_p
)
1722 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1724 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1731 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1733 /* Block input so that we won't be interrupted by a SIGIO
1734 while being in an inconsistent state. */
1737 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1739 struct image
*img
= c
->images
[i
];
1741 && (force_p
|| img
->timestamp
< old
))
1743 free_image (f
, img
);
1748 /* We may be clearing the image cache because, for example,
1749 Emacs was iconified for a longer period of time. In that
1750 case, current matrices may still contain references to
1751 images freed above. So, clear these matrices. */
1754 Lisp_Object tail
, frame
;
1756 FOR_EACH_FRAME (tail
, frame
)
1758 struct frame
*f
= XFRAME (frame
);
1759 if (FRAME_WINDOW_P (f
)
1760 && FRAME_X_IMAGE_CACHE (f
) == c
)
1761 clear_current_matrices (f
);
1764 ++windows_or_buffers_changed
;
1772 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1774 doc
: /* Clear the image cache of FRAME.
1775 FRAME nil or omitted means use the selected frame.
1776 FRAME t means clear the image caches of all frames. */)
1784 FOR_EACH_FRAME (tail
, frame
)
1785 if (FRAME_WINDOW_P (XFRAME (frame
)))
1786 clear_image_cache (XFRAME (frame
), 1);
1789 clear_image_cache (check_x_frame (frame
), 1);
1795 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1797 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1798 If SPEC specifies an image file, the displayed image is updated with
1799 the current contents of that file.
1800 FRAME nil or omitted means use the selected frame.
1801 FRAME t means refresh the image on all frames. */)
1803 Lisp_Object spec
, frame
;
1805 if (!valid_image_p (spec
))
1806 error ("Invalid image specification");
1811 FOR_EACH_FRAME (tail
, frame
)
1813 struct frame
*f
= XFRAME (frame
);
1814 if (FRAME_WINDOW_P (f
))
1815 uncache_image (f
, spec
);
1819 uncache_image (check_x_frame (frame
), spec
);
1825 /* Compute masks and transform image IMG on frame F, as specified
1826 by the image's specification, */
1829 postprocess_image (f
, img
)
1833 /* Manipulation of the image's mask. */
1836 Lisp_Object conversion
, spec
;
1841 /* `:heuristic-mask t'
1843 means build a mask heuristically.
1844 `:heuristic-mask (R G B)'
1845 `:mask (heuristic (R G B))'
1846 means build a mask from color (R G B) in the
1849 means remove a mask, if any. */
1851 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1853 x_build_heuristic_mask (f
, img
, mask
);
1858 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1860 if (EQ (mask
, Qheuristic
))
1861 x_build_heuristic_mask (f
, img
, Qt
);
1862 else if (CONSP (mask
)
1863 && EQ (XCAR (mask
), Qheuristic
))
1865 if (CONSP (XCDR (mask
)))
1866 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1868 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1870 else if (NILP (mask
) && found_p
&& img
->mask
)
1872 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1873 img
->mask
= NO_PIXMAP
;
1878 /* Should we apply an image transformation algorithm? */
1879 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1880 if (EQ (conversion
, Qdisabled
))
1881 x_disable_image (f
, img
);
1882 else if (EQ (conversion
, Qlaplace
))
1884 else if (EQ (conversion
, Qemboss
))
1886 else if (CONSP (conversion
)
1887 && EQ (XCAR (conversion
), Qedge_detection
))
1890 tem
= XCDR (conversion
);
1892 x_edge_detection (f
, img
,
1893 Fplist_get (tem
, QCmatrix
),
1894 Fplist_get (tem
, QCcolor_adjustment
));
1900 /* Return the id of image with Lisp specification SPEC on frame F.
1901 SPEC must be a valid Lisp image specification (see valid_image_p). */
1904 lookup_image (f
, spec
)
1910 struct gcpro gcpro1
;
1913 /* F must be a window-system frame, and SPEC must be a valid image
1915 xassert (FRAME_WINDOW_P (f
));
1916 xassert (valid_image_p (spec
));
1920 /* Look up SPEC in the hash table of the image cache. */
1921 hash
= sxhash (spec
, 0);
1922 img
= search_image_cache (f
, spec
, hash
);
1923 if (img
&& img
->load_failed_p
)
1925 free_image (f
, img
);
1929 /* If not found, create a new image and cache it. */
1932 extern Lisp_Object Qpostscript
;
1935 img
= make_image (spec
, hash
);
1936 cache_image (f
, img
);
1937 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1938 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
1939 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
1941 /* If we can't load the image, and we don't have a width and
1942 height, use some arbitrary width and height so that we can
1943 draw a rectangle for it. */
1944 if (img
->load_failed_p
)
1948 value
= image_spec_value (spec
, QCwidth
, NULL
);
1949 img
->width
= (INTEGERP (value
)
1950 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1951 value
= image_spec_value (spec
, QCheight
, NULL
);
1952 img
->height
= (INTEGERP (value
)
1953 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1957 /* Handle image type independent image attributes
1958 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1959 `:background COLOR'. */
1960 Lisp_Object ascent
, margin
, relief
, bg
;
1962 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1963 if (INTEGERP (ascent
))
1964 img
->ascent
= XFASTINT (ascent
);
1965 else if (EQ (ascent
, Qcenter
))
1966 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1968 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1969 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1970 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1971 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1972 && INTEGERP (XCDR (margin
)))
1974 if (XINT (XCAR (margin
)) > 0)
1975 img
->hmargin
= XFASTINT (XCAR (margin
));
1976 if (XINT (XCDR (margin
)) > 0)
1977 img
->vmargin
= XFASTINT (XCDR (margin
));
1980 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1981 if (INTEGERP (relief
))
1983 img
->relief
= XINT (relief
);
1984 img
->hmargin
+= abs (img
->relief
);
1985 img
->vmargin
+= abs (img
->relief
);
1988 if (! img
->background_valid
)
1990 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1994 = x_alloc_image_color (f
, img
, bg
,
1995 FRAME_BACKGROUND_PIXEL (f
));
1996 img
->background_valid
= 1;
2000 /* Do image transformations and compute masks, unless we
2001 don't have the image yet. */
2002 if (!EQ (*img
->type
->type
, Qpostscript
))
2003 postprocess_image (f
, img
);
2009 /* We're using IMG, so set its timestamp to `now'. */
2010 EMACS_GET_TIME (now
);
2011 img
->timestamp
= EMACS_SECS (now
);
2015 /* Value is the image id. */
2020 /* Cache image IMG in the image cache of frame F. */
2023 cache_image (f
, img
)
2027 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2030 /* Find a free slot in c->images. */
2031 for (i
= 0; i
< c
->used
; ++i
)
2032 if (c
->images
[i
] == NULL
)
2035 /* If no free slot found, maybe enlarge c->images. */
2036 if (i
== c
->used
&& c
->used
== c
->size
)
2039 c
->images
= (struct image
**) xrealloc (c
->images
,
2040 c
->size
* sizeof *c
->images
);
2043 /* Add IMG to c->images, and assign IMG an id. */
2049 /* Add IMG to the cache's hash table. */
2050 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2051 img
->next
= c
->buckets
[i
];
2053 img
->next
->prev
= img
;
2055 c
->buckets
[i
] = img
;
2059 /* Call FN on every image in the image cache of frame F. Used to mark
2060 Lisp Objects in the image cache. */
2063 forall_images_in_image_cache (f
, fn
)
2065 void (*fn
) P_ ((struct image
*img
));
2067 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
2069 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2073 for (i
= 0; i
< c
->used
; ++i
)
2082 /***********************************************************************
2083 X / MAC / W32 support code
2084 ***********************************************************************/
2088 /* Macro for defining functions that will be loaded from image DLLs. */
2089 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2091 /* Macro for loading those image functions from the library. */
2092 #define LOAD_IMGLIB_FN(lib,func) { \
2093 fn_##func = (void *) GetProcAddress (lib, #func); \
2094 if (!fn_##func) return 0; \
2097 /* Load a DLL implementing an image type.
2098 The `image-library-alist' variable associates a symbol,
2099 identifying an image type, to a list of possible filenames.
2100 The function returns NULL if no library could be loaded for
2101 the given image type, or if the library was previously loaded;
2102 else the handle of the DLL. */
2104 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2106 HMODULE library
= NULL
;
2108 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2110 Lisp_Object dlls
= Fassq (type
, libraries
);
2113 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2115 CHECK_STRING_CAR (dlls
);
2116 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2124 #endif /* HAVE_NTGUI */
2126 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2127 XImagePtr
*, Pixmap
*));
2128 static void x_destroy_x_image
P_ ((XImagePtr
));
2129 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2132 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2133 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2134 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2135 via xmalloc. Print error messages via image_error if an error
2136 occurs. Value is non-zero if successful.
2138 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2139 should indicate the bit depth of the image. */
2142 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2144 int width
, height
, depth
;
2148 #ifdef HAVE_X_WINDOWS
2149 Display
*display
= FRAME_X_DISPLAY (f
);
2150 Window window
= FRAME_X_WINDOW (f
);
2151 Screen
*screen
= FRAME_X_SCREEN (f
);
2153 xassert (interrupt_input_blocked
);
2156 depth
= DefaultDepthOfScreen (screen
);
2157 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2158 depth
, ZPixmap
, 0, NULL
, width
, height
,
2159 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2162 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2166 /* Allocate image raster. */
2167 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2169 /* Allocate a pixmap of the same size. */
2170 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2171 if (*pixmap
== NO_PIXMAP
)
2173 x_destroy_x_image (*ximg
);
2175 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2180 #endif /* HAVE_X_WINDOWS */
2184 BITMAPINFOHEADER
*header
;
2186 int scanline_width_bits
;
2188 int palette_colors
= 0;
2193 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2194 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2196 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2200 scanline_width_bits
= width
* depth
;
2201 remainder
= scanline_width_bits
% 32;
2204 scanline_width_bits
+= 32 - remainder
;
2206 /* Bitmaps with a depth less than 16 need a palette. */
2207 /* BITMAPINFO structure already contains the first RGBQUAD. */
2209 palette_colors
= 1 << depth
- 1;
2211 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2214 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2218 header
= &((*ximg
)->info
.bmiHeader
);
2219 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2220 header
->biSize
= sizeof (*header
);
2221 header
->biWidth
= width
;
2222 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2223 header
->biPlanes
= 1;
2224 header
->biBitCount
= depth
;
2225 header
->biCompression
= BI_RGB
;
2226 header
->biClrUsed
= palette_colors
;
2228 /* TODO: fill in palette. */
2231 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2232 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2233 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2234 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2235 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2236 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2237 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2238 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2241 hdc
= get_frame_dc (f
);
2243 /* Create a DIBSection and raster array for the bitmap,
2244 and store its handle in *pixmap. */
2245 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2246 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2247 /* casting avoids a GCC warning */
2248 (void **)&((*ximg
)->data
), NULL
, 0);
2250 /* Realize display palette and garbage all frames. */
2251 release_frame_dc (f
, hdc
);
2253 if (*pixmap
== NULL
)
2255 DWORD err
= GetLastError();
2256 Lisp_Object errcode
;
2257 /* All system errors are < 10000, so the following is safe. */
2258 XSETINT (errcode
, (int) err
);
2259 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2260 x_destroy_x_image (*ximg
);
2266 #endif /* HAVE_NTGUI */
2269 Display
*display
= FRAME_X_DISPLAY (f
);
2270 Window window
= FRAME_X_WINDOW (f
);
2272 xassert (interrupt_input_blocked
);
2274 /* Allocate a pixmap of the same size. */
2275 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2276 if (*pixmap
== NO_PIXMAP
)
2279 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2283 LockPixels (GetGWorldPixMap (*pixmap
));
2291 /* Destroy XImage XIMG. Free XIMG->data. */
2294 x_destroy_x_image (ximg
)
2297 xassert (interrupt_input_blocked
);
2300 #ifdef HAVE_X_WINDOWS
2303 XDestroyImage (ximg
);
2304 #endif /* HAVE_X_WINDOWS */
2306 /* Data will be freed by DestroyObject. */
2309 #endif /* HAVE_NTGUI */
2311 XDestroyImage (ximg
);
2317 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2318 are width and height of both the image and pixmap. */
2321 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2327 #ifdef HAVE_X_WINDOWS
2330 xassert (interrupt_input_blocked
);
2331 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2332 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2333 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2334 #endif /* HAVE_X_WINDOWS */
2337 #if 0 /* I don't think this is necessary looking at where it is used. */
2338 HDC hdc
= get_frame_dc (f
);
2339 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2340 release_frame_dc (f
, hdc
);
2342 #endif /* HAVE_NTGUI */
2345 xassert (ximg
== pixmap
);
2350 /***********************************************************************
2352 ***********************************************************************/
2354 static unsigned char *slurp_file
P_ ((char *, int *));
2357 /* Find image file FILE. Look in data-directory/images, then
2358 x-bitmap-file-path. Value is the encoded full name of the file
2359 found, or nil if not found. */
2362 x_find_image_file (file
)
2365 Lisp_Object file_found
, search_path
;
2366 struct gcpro gcpro1
, gcpro2
;
2370 /* TODO I think this should use something like image-load-path
2371 instead. Unfortunately, that can contain non-string elements. */
2372 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2374 Vx_bitmap_file_path
);
2375 GCPRO2 (file_found
, search_path
);
2377 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2378 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2384 file_found
= ENCODE_FILE (file_found
);
2393 /* Read FILE into memory. Value is a pointer to a buffer allocated
2394 with xmalloc holding FILE's contents. Value is null if an error
2395 occurred. *SIZE is set to the size of the file. */
2397 static unsigned char *
2398 slurp_file (file
, size
)
2403 unsigned char *buf
= NULL
;
2406 if (stat (file
, &st
) == 0
2407 && (fp
= fopen (file
, "rb")) != NULL
2408 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2409 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2432 /***********************************************************************
2433 MAC Image Load Functions
2434 ***********************************************************************/
2436 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2439 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2443 find_image_fsspec (specified_file
, file
, fss
)
2444 Lisp_Object specified_file
, *file
;
2450 *file
= x_find_image_file (specified_file
);
2451 if (!STRINGP (*file
))
2452 return fnfErr
; /* file or directory not found;
2453 incomplete pathname */
2454 /* Try to open the image file. */
2455 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2456 SBYTES (*file
), typeFSS
, &desc
);
2459 #if TARGET_API_MAC_CARBON
2460 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2462 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2464 AEDisposeDesc (&desc
);
2470 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2477 ComponentResult err
;
2478 GraphicsImportComponent gi
;
2481 ImageDescriptionHandle desc_handle
;
2482 short draw_all_pixels
;
2483 Lisp_Object specified_bg
;
2488 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2491 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2496 /* read from file system spec */
2497 err
= GraphicsImportSetDataFile (gi
, fss
);
2500 image_error ("Cannot set fsspec to graphics importer for '%s'",
2507 /* read from data handle */
2508 err
= GraphicsImportSetDataHandle (gi
, dh
);
2511 image_error ("Cannot set data handle to graphics importer for `%s'",
2516 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2517 if (err
!= noErr
|| desc_handle
== NULL
)
2519 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2522 width
= img
->width
= (*desc_handle
)->width
;
2523 height
= img
->height
= (*desc_handle
)->height
;
2524 DisposeHandle ((Handle
)desc_handle
);
2526 if (!check_image_size (f
, width
, height
))
2528 image_error ("Invalid image size", Qnil
, Qnil
);
2532 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2534 /* Don't check the error code here. It may have an undocumented
2538 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2542 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2544 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2545 if (!STRINGP (specified_bg
) ||
2546 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2548 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2549 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2550 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2551 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2555 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2557 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2562 GetGWorld (&old_port
, &old_gdh
);
2563 SetGWorld (ximg
, NULL
);
2564 bg_color
.red
= color
.red
;
2565 bg_color
.green
= color
.green
;
2566 bg_color
.blue
= color
.blue
;
2567 RGBBackColor (&bg_color
);
2568 #if TARGET_API_MAC_CARBON
2569 GetPortBounds (ximg
, &rect
);
2572 EraseRect (&(ximg
->portRect
));
2574 SetGWorld (old_port
, old_gdh
);
2576 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2577 GraphicsImportDraw (gi
);
2578 CloseComponent (gi
);
2580 /* Maybe fill in the background field while we have ximg handy. */
2581 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2582 IMAGE_BACKGROUND (img
, f
, ximg
);
2584 /* Put the image into the pixmap. */
2585 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2586 x_destroy_x_image (ximg
);
2590 CloseComponent (gi
);
2595 /* Load an image using the QuickTime Graphics Importer.
2596 Note: The alpha channel does not work for PNG images. */
2598 image_load_quicktime (f
, img
, type
)
2603 Lisp_Object specified_file
;
2604 Lisp_Object specified_data
;
2607 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2608 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2610 if (NILP (specified_data
))
2612 /* Read from a file */
2616 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2620 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2622 image_error ("Cannot open `%s'", file
, Qnil
);
2625 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2629 /* Memory source! */
2633 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2636 image_error ("Cannot allocate data handle for `%s'",
2640 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2648 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2649 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2650 So don't use this function directly but determine at runtime
2651 whether it exists. */
2652 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2653 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2654 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2658 init_image_func_pointer ()
2660 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2662 MyCGImageCreateWithPNGDataProvider
2663 = (CGImageCreateWithPNGDataProviderProcType
)
2664 NSAddressOfSymbol (NSLookupAndBindSymbol
2665 ("_CGImageCreateWithPNGDataProvider"));
2668 MyCGImageCreateWithPNGDataProvider
= NULL
;
2673 image_load_quartz2d (f
, img
, png_p
)
2678 Lisp_Object file
, specified_file
;
2679 Lisp_Object specified_data
, specified_bg
;
2680 struct gcpro gcpro1
;
2681 CGDataProviderRef source
;
2685 XImagePtr ximg
= NULL
;
2686 CGContextRef context
;
2689 /* Open the file. */
2690 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2691 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2696 if (NILP (specified_data
))
2701 file
= x_find_image_file (specified_file
);
2702 if (!STRINGP (file
))
2704 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2708 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2709 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2710 kCFURLPOSIXPathStyle
, 0);
2712 source
= CGDataProviderCreateWithURL (url
);
2716 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2717 SBYTES (specified_data
), NULL
);
2720 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2721 kCGRenderingIntentDefault
);
2723 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2724 kCGRenderingIntentDefault
);
2726 CGDataProviderRelease (source
);
2730 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2733 width
= img
->width
= CGImageGetWidth (image
);
2734 height
= img
->height
= CGImageGetHeight (image
);
2736 if (!check_image_size (f
, width
, height
))
2738 CGImageRelease (image
);
2740 image_error ("Invalid image size", Qnil
, Qnil
);
2746 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2747 if (!STRINGP (specified_bg
) ||
2748 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2750 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2751 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2752 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2753 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2757 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2759 CGImageRelease (image
);
2763 rectangle
= CGRectMake (0, 0, width
, height
);
2764 QDBeginCGContext (ximg
, &context
);
2767 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2768 color
.green
/ 65535.0,
2769 color
.blue
/ 65535.0, 1.0);
2770 CGContextFillRect (context
, rectangle
);
2772 CGContextDrawImage (context
, rectangle
, image
);
2773 QDEndCGContext (ximg
, &context
);
2774 CGImageRelease (image
);
2776 /* Maybe fill in the background field while we have ximg handy. */
2777 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2778 IMAGE_BACKGROUND (img
, f
, ximg
);
2780 /* Put the image into the pixmap. */
2781 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2782 x_destroy_x_image (ximg
);
2791 /***********************************************************************
2793 ***********************************************************************/
2795 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2796 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2797 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2798 unsigned char *, unsigned char *));
2799 static int xbm_image_p
P_ ((Lisp_Object object
));
2800 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2801 unsigned char *, unsigned char *,
2802 int *, int *, unsigned char **));
2803 static int xbm_file_p
P_ ((Lisp_Object
));
2806 /* Indices of image specification fields in xbm_format, below. */
2808 enum xbm_keyword_index
2826 /* Vector of image_keyword structures describing the format
2827 of valid XBM image specifications. */
2829 static struct image_keyword xbm_format
[XBM_LAST
] =
2831 {":type", IMAGE_SYMBOL_VALUE
, 1},
2832 {":file", IMAGE_STRING_VALUE
, 0},
2833 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2834 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2835 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2836 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2837 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2838 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2839 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2840 {":relief", IMAGE_INTEGER_VALUE
, 0},
2841 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2842 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2843 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2846 /* Structure describing the image type XBM. */
2848 static struct image_type xbm_type
=
2857 /* Tokens returned from xbm_scan. */
2866 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2867 A valid specification is a list starting with the symbol `image'
2868 The rest of the list is a property list which must contain an
2871 If the specification specifies a file to load, it must contain
2872 an entry `:file FILENAME' where FILENAME is a string.
2874 If the specification is for a bitmap loaded from memory it must
2875 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2876 WIDTH and HEIGHT are integers > 0. DATA may be:
2878 1. a string large enough to hold the bitmap data, i.e. it must
2879 have a size >= (WIDTH + 7) / 8 * HEIGHT
2881 2. a bool-vector of size >= WIDTH * HEIGHT
2883 3. a vector of strings or bool-vectors, one for each line of the
2886 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2887 may not be specified in this case because they are defined in the
2890 Both the file and data forms may contain the additional entries
2891 `:background COLOR' and `:foreground COLOR'. If not present,
2892 foreground and background of the frame on which the image is
2893 displayed is used. */
2896 xbm_image_p (object
)
2899 struct image_keyword kw
[XBM_LAST
];
2901 bcopy (xbm_format
, kw
, sizeof kw
);
2902 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2905 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2907 if (kw
[XBM_FILE
].count
)
2909 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2912 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2914 /* In-memory XBM file. */
2915 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2923 /* Entries for `:width', `:height' and `:data' must be present. */
2924 if (!kw
[XBM_WIDTH
].count
2925 || !kw
[XBM_HEIGHT
].count
2926 || !kw
[XBM_DATA
].count
)
2929 data
= kw
[XBM_DATA
].value
;
2930 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2931 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2933 /* Check type of data, and width and height against contents of
2939 /* Number of elements of the vector must be >= height. */
2940 if (XVECTOR (data
)->size
< height
)
2943 /* Each string or bool-vector in data must be large enough
2944 for one line of the image. */
2945 for (i
= 0; i
< height
; ++i
)
2947 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2952 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2955 else if (BOOL_VECTOR_P (elt
))
2957 if (XBOOL_VECTOR (elt
)->size
< width
)
2964 else if (STRINGP (data
))
2967 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2970 else if (BOOL_VECTOR_P (data
))
2972 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2983 /* Scan a bitmap file. FP is the stream to read from. Value is
2984 either an enumerator from enum xbm_token, or a character for a
2985 single-character token, or 0 at end of file. If scanning an
2986 identifier, store the lexeme of the identifier in SVAL. If
2987 scanning a number, store its value in *IVAL. */
2990 xbm_scan (s
, end
, sval
, ival
)
2991 unsigned char **s
, *end
;
2999 /* Skip white space. */
3000 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3005 else if (isdigit (c
))
3007 int value
= 0, digit
;
3009 if (c
== '0' && *s
< end
)
3012 if (c
== 'x' || c
== 'X')
3019 else if (c
>= 'a' && c
<= 'f')
3020 digit
= c
- 'a' + 10;
3021 else if (c
>= 'A' && c
<= 'F')
3022 digit
= c
- 'A' + 10;
3025 value
= 16 * value
+ digit
;
3028 else if (isdigit (c
))
3032 && (c
= *(*s
)++, isdigit (c
)))
3033 value
= 8 * value
+ c
- '0';
3040 && (c
= *(*s
)++, isdigit (c
)))
3041 value
= 10 * value
+ c
- '0';
3049 else if (isalpha (c
) || c
== '_')
3053 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3060 else if (c
== '/' && **s
== '*')
3062 /* C-style comment. */
3064 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3078 /* Create a Windows bitmap from X bitmap data. */
3080 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3082 static unsigned char swap_nibble
[16]
3083 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3084 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3085 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3086 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3088 unsigned char *bits
, *p
;
3091 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3092 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3093 bits
= (unsigned char *) alloca (height
* w2
);
3094 bzero (bits
, height
* w2
);
3095 for (i
= 0; i
< height
; i
++)
3098 for (j
= 0; j
< w1
; j
++)
3100 /* Bitswap XBM bytes to match how Windows does things. */
3101 unsigned char c
= *data
++;
3102 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3103 | (swap_nibble
[(c
>>4) & 0xf]));
3106 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3111 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
3114 COLORREF foreground
, background
;
3116 HDC hdc
, old_img_dc
, new_img_dc
;
3117 HGDIOBJ old_prev
, new_prev
;
3120 hdc
= get_frame_dc (f
);
3121 old_img_dc
= CreateCompatibleDC (hdc
);
3122 new_img_dc
= CreateCompatibleDC (hdc
);
3123 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3124 release_frame_dc (f
, hdc
);
3125 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3126 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3127 SetTextColor (new_img_dc
, background
);
3128 SetBkColor (new_img_dc
, foreground
);
3130 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3133 SelectObject (old_img_dc
, old_prev
);
3134 SelectObject (new_img_dc
, new_prev
);
3135 DeleteDC (old_img_dc
);
3136 DeleteDC (new_img_dc
);
3137 DeleteObject (img
->pixmap
);
3138 if (new_pixmap
== 0)
3139 fprintf (stderr
, "Failed to convert image to color.\n");
3141 img
->pixmap
= new_pixmap
;
3144 #define XBM_BIT_SHUFFLE(b) (~(b))
3148 #define XBM_BIT_SHUFFLE(b) (b)
3150 #endif /* HAVE_NTGUI */
3154 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
3158 RGB_PIXEL_COLOR fg
, bg
;
3159 int non_default_colors
;
3163 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3165 /* If colors were specified, transfer the bitmap to a color one. */
3166 if (non_default_colors
)
3167 convert_mono_to_color_image (f
, img
, fg
, bg
);
3170 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3173 img
->width
, img
->height
,
3175 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3176 #endif /* HAVE_NTGUI */
3181 /* Replacement for XReadBitmapFileData which isn't available under old
3182 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3183 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3184 the image. Return in *DATA the bitmap data allocated with xmalloc.
3185 Value is non-zero if successful. DATA null means just test if
3186 CONTENTS looks like an in-memory XBM file. */
3189 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3191 unsigned char *contents
, *end
;
3192 int *width
, *height
;
3193 unsigned char **data
;
3195 unsigned char *s
= contents
;
3196 char buffer
[BUFSIZ
];
3199 int bytes_per_line
, i
, nbytes
;
3205 LA1 = xbm_scan (&s, end, buffer, &value)
3207 #define expect(TOKEN) \
3208 if (LA1 != (TOKEN)) \
3213 #define expect_ident(IDENT) \
3214 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3219 *width
= *height
= -1;
3222 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3224 /* Parse defines for width, height and hot-spots. */
3228 expect_ident ("define");
3229 expect (XBM_TK_IDENT
);
3231 if (LA1
== XBM_TK_NUMBER
)
3233 char *p
= strrchr (buffer
, '_');
3234 p
= p
? p
+ 1 : buffer
;
3235 if (strcmp (p
, "width") == 0)
3237 else if (strcmp (p
, "height") == 0)
3240 expect (XBM_TK_NUMBER
);
3243 if (!check_image_size (f
, *width
, *height
))
3245 else if (data
== NULL
)
3248 /* Parse bits. Must start with `static'. */
3249 expect_ident ("static");
3250 if (LA1
== XBM_TK_IDENT
)
3252 if (strcmp (buffer
, "unsigned") == 0)
3255 expect_ident ("char");
3257 else if (strcmp (buffer
, "short") == 0)
3261 if (*width
% 16 && *width
% 16 < 9)
3264 else if (strcmp (buffer
, "char") == 0)
3272 expect (XBM_TK_IDENT
);
3278 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3279 nbytes
= bytes_per_line
* *height
;
3280 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3284 for (i
= 0; i
< nbytes
; i
+= 2)
3287 expect (XBM_TK_NUMBER
);
3289 *p
++ = XBM_BIT_SHUFFLE (val
);
3290 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3291 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3293 if (LA1
== ',' || LA1
== '}')
3301 for (i
= 0; i
< nbytes
; ++i
)
3304 expect (XBM_TK_NUMBER
);
3306 *p
++ = XBM_BIT_SHUFFLE (val
);
3308 if (LA1
== ',' || LA1
== '}')
3333 /* Load XBM image IMG which will be displayed on frame F from buffer
3334 CONTENTS. END is the end of the buffer. Value is non-zero if
3338 xbm_load_image (f
, img
, contents
, end
)
3341 unsigned char *contents
, *end
;
3344 unsigned char *data
;
3347 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3350 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3351 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3352 int non_default_colors
= 0;
3355 xassert (img
->width
> 0 && img
->height
> 0);
3357 /* Get foreground and background colors, maybe allocate colors. */
3358 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3361 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3362 non_default_colors
= 1;
3364 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3367 background
= x_alloc_image_color (f
, img
, value
, background
);
3368 img
->background
= background
;
3369 img
->background_valid
= 1;
3370 non_default_colors
= 1;
3373 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3374 foreground
, background
,
3375 non_default_colors
);
3378 if (img
->pixmap
== NO_PIXMAP
)
3380 x_clear_image (f
, img
);
3381 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3387 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3393 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3400 return (STRINGP (data
)
3401 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3408 /* Fill image IMG which is used on frame F with pixmap data. Value is
3409 non-zero if successful. */
3417 Lisp_Object file_name
;
3419 xassert (xbm_image_p (img
->spec
));
3421 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3422 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3423 if (STRINGP (file_name
))
3426 unsigned char *contents
;
3428 struct gcpro gcpro1
;
3430 file
= x_find_image_file (file_name
);
3432 if (!STRINGP (file
))
3434 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3439 contents
= slurp_file (SDATA (file
), &size
);
3440 if (contents
== NULL
)
3442 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3447 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3452 struct image_keyword fmt
[XBM_LAST
];
3454 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3455 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3456 int non_default_colors
= 0;
3459 int in_memory_file_p
= 0;
3461 /* See if data looks like an in-memory XBM file. */
3462 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3463 in_memory_file_p
= xbm_file_p (data
);
3465 /* Parse the image specification. */
3466 bcopy (xbm_format
, fmt
, sizeof fmt
);
3467 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3470 /* Get specified width, and height. */
3471 if (!in_memory_file_p
)
3473 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3474 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3475 xassert (img
->width
> 0 && img
->height
> 0);
3478 /* Get foreground and background colors, maybe allocate colors. */
3479 if (fmt
[XBM_FOREGROUND
].count
3480 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3482 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3484 non_default_colors
= 1;
3487 if (fmt
[XBM_BACKGROUND
].count
3488 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3490 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3492 non_default_colors
= 1;
3495 if (in_memory_file_p
)
3496 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3505 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3507 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3508 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3510 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3512 bcopy (SDATA (line
), p
, nbytes
);
3514 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3517 else if (STRINGP (data
))
3518 bits
= SDATA (data
);
3520 bits
= XBOOL_VECTOR (data
)->data
;
3522 /* Create the pixmap. */
3524 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3525 foreground
, background
,
3526 non_default_colors
);
3531 image_error ("Unable to create pixmap for XBM image `%s'",
3533 x_clear_image (f
, img
);
3543 /***********************************************************************
3545 ***********************************************************************/
3547 #if defined (HAVE_XPM) || defined (MAC_OS)
3549 static int xpm_image_p
P_ ((Lisp_Object object
));
3550 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3551 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3553 #endif /* HAVE_XPM || MAC_OS */
3557 /* Indicate to xpm.h that we don't have Xlib. */
3559 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3560 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3561 #define XColor xpm_XColor
3562 #define XImage xpm_XImage
3563 #define Display xpm_Display
3564 #define PIXEL_ALREADY_TYPEDEFED
3565 #include "X11/xpm.h"
3570 #undef PIXEL_ALREADY_TYPEDEFED
3572 #include "X11/xpm.h"
3573 #endif /* HAVE_NTGUI */
3574 #endif /* HAVE_XPM */
3576 #if defined (HAVE_XPM) || defined (MAC_OS)
3577 /* The symbol `xpm' identifying XPM-format images. */
3581 /* Indices of image specification fields in xpm_format, below. */
3583 enum xpm_keyword_index
3599 /* Vector of image_keyword structures describing the format
3600 of valid XPM image specifications. */
3602 static struct image_keyword xpm_format
[XPM_LAST
] =
3604 {":type", IMAGE_SYMBOL_VALUE
, 1},
3605 {":file", IMAGE_STRING_VALUE
, 0},
3606 {":data", IMAGE_STRING_VALUE
, 0},
3607 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3608 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3609 {":relief", IMAGE_INTEGER_VALUE
, 0},
3610 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3611 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3612 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3613 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3614 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3617 /* Structure describing the image type XPM. */
3619 static struct image_type xpm_type
=
3628 #ifdef HAVE_X_WINDOWS
3630 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3631 functions for allocating image colors. Our own functions handle
3632 color allocation failures more gracefully than the ones on the XPM
3635 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3636 #define ALLOC_XPM_COLORS
3638 #endif /* HAVE_X_WINDOWS */
3640 #ifdef ALLOC_XPM_COLORS
3642 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3643 static void xpm_free_color_cache
P_ ((void));
3644 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3645 static int xpm_color_bucket
P_ ((char *));
3646 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3649 /* An entry in a hash table used to cache color definitions of named
3650 colors. This cache is necessary to speed up XPM image loading in
3651 case we do color allocations ourselves. Without it, we would need
3652 a call to XParseColor per pixel in the image. */
3654 struct xpm_cached_color
3656 /* Next in collision chain. */
3657 struct xpm_cached_color
*next
;
3659 /* Color definition (RGB and pixel color). */
3666 /* The hash table used for the color cache, and its bucket vector
3669 #define XPM_COLOR_CACHE_BUCKETS 1001
3670 struct xpm_cached_color
**xpm_color_cache
;
3672 /* Initialize the color cache. */
3675 xpm_init_color_cache (f
, attrs
)
3677 XpmAttributes
*attrs
;
3679 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3680 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3681 memset (xpm_color_cache
, 0, nbytes
);
3682 init_color_table ();
3684 if (attrs
->valuemask
& XpmColorSymbols
)
3689 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3690 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3691 attrs
->colorsymbols
[i
].value
, &color
))
3693 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3695 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3700 /* Free the color cache. */
3703 xpm_free_color_cache ()
3705 struct xpm_cached_color
*p
, *next
;
3708 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3709 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3715 xfree (xpm_color_cache
);
3716 xpm_color_cache
= NULL
;
3717 free_color_table ();
3720 /* Return the bucket index for color named COLOR_NAME in the color
3724 xpm_color_bucket (color_name
)
3730 for (s
= color_name
; *s
; ++s
)
3732 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3736 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3737 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3740 static struct xpm_cached_color
*
3741 xpm_cache_color (f
, color_name
, color
, bucket
)
3748 struct xpm_cached_color
*p
;
3751 bucket
= xpm_color_bucket (color_name
);
3753 nbytes
= sizeof *p
+ strlen (color_name
);
3754 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3755 strcpy (p
->name
, color_name
);
3757 p
->next
= xpm_color_cache
[bucket
];
3758 xpm_color_cache
[bucket
] = p
;
3762 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3763 return the cached definition in *COLOR. Otherwise, make a new
3764 entry in the cache and allocate the color. Value is zero if color
3765 allocation failed. */
3768 xpm_lookup_color (f
, color_name
, color
)
3773 struct xpm_cached_color
*p
;
3774 int h
= xpm_color_bucket (color_name
);
3776 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3777 if (strcmp (p
->name
, color_name
) == 0)
3782 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3785 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3787 p
= xpm_cache_color (f
, color_name
, color
, h
);
3789 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3790 with transparency, and it's useful. */
3791 else if (strcmp ("opaque", color_name
) == 0)
3793 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3794 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3795 p
= xpm_cache_color (f
, color_name
, color
, h
);
3802 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3803 CLOSURE is a pointer to the frame on which we allocate the
3804 color. Return in *COLOR the allocated color. Value is non-zero
3808 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3815 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3819 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3820 is a pointer to the frame on which we allocate the color. Value is
3821 non-zero if successful. */
3824 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3834 #endif /* ALLOC_XPM_COLORS */
3839 /* XPM library details. */
3841 DEF_IMGLIB_FN (XpmFreeAttributes
);
3842 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3843 DEF_IMGLIB_FN (XpmReadFileToImage
);
3844 DEF_IMGLIB_FN (XImageFree
);
3847 init_xpm_functions (Lisp_Object libraries
)
3851 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3854 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3855 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3856 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3857 LOAD_IMGLIB_FN (library
, XImageFree
);
3861 #endif /* HAVE_NTGUI */
3864 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3865 for XPM images. Such a list must consist of conses whose car and
3869 xpm_valid_color_symbols_p (color_symbols
)
3870 Lisp_Object color_symbols
;
3872 while (CONSP (color_symbols
))
3874 Lisp_Object sym
= XCAR (color_symbols
);
3876 || !STRINGP (XCAR (sym
))
3877 || !STRINGP (XCDR (sym
)))
3879 color_symbols
= XCDR (color_symbols
);
3882 return NILP (color_symbols
);
3886 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3889 xpm_image_p (object
)
3892 struct image_keyword fmt
[XPM_LAST
];
3893 bcopy (xpm_format
, fmt
, sizeof fmt
);
3894 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3895 /* Either `:file' or `:data' must be present. */
3896 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3897 /* Either no `:color-symbols' or it's a list of conses
3898 whose car and cdr are strings. */
3899 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3900 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3903 #endif /* HAVE_XPM || MAC_OS */
3905 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3907 x_create_bitmap_from_xpm_data (f
, bits
)
3911 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3913 XpmAttributes attrs
;
3914 Pixmap bitmap
, mask
;
3916 bzero (&attrs
, sizeof attrs
);
3918 attrs
.visual
= FRAME_X_VISUAL (f
);
3919 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3920 attrs
.valuemask
|= XpmVisual
;
3921 attrs
.valuemask
|= XpmColormap
;
3923 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3924 bits
, &bitmap
, &mask
, &attrs
);
3925 if (rc
!= XpmSuccess
)
3927 XpmFreeAttributes (&attrs
);
3931 id
= x_allocate_bitmap_record (f
);
3932 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3933 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3934 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3935 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3936 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3937 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3938 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3939 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3941 XpmFreeAttributes (&attrs
);
3944 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3946 /* Load image IMG which will be displayed on frame F. Value is
3947 non-zero if successful. */
3957 XpmAttributes attrs
;
3958 Lisp_Object specified_file
, color_symbols
;
3961 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3962 #endif /* HAVE_NTGUI */
3964 /* Configure the XPM lib. Use the visual of frame F. Allocate
3965 close colors. Return colors allocated. */
3966 bzero (&attrs
, sizeof attrs
);
3969 attrs
.visual
= FRAME_X_VISUAL (f
);
3970 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3971 attrs
.valuemask
|= XpmVisual
;
3972 attrs
.valuemask
|= XpmColormap
;
3973 #endif /* HAVE_NTGUI */
3975 #ifdef ALLOC_XPM_COLORS
3976 /* Allocate colors with our own functions which handle
3977 failing color allocation more gracefully. */
3978 attrs
.color_closure
= f
;
3979 attrs
.alloc_color
= xpm_alloc_color
;
3980 attrs
.free_colors
= xpm_free_colors
;
3981 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3982 #else /* not ALLOC_XPM_COLORS */
3983 /* Let the XPM lib allocate colors. */
3984 attrs
.valuemask
|= XpmReturnAllocPixels
;
3985 #ifdef XpmAllocCloseColors
3986 attrs
.alloc_close_colors
= 1;
3987 attrs
.valuemask
|= XpmAllocCloseColors
;
3988 #else /* not XpmAllocCloseColors */
3989 attrs
.closeness
= 600;
3990 attrs
.valuemask
|= XpmCloseness
;
3991 #endif /* not XpmAllocCloseColors */
3992 #endif /* ALLOC_XPM_COLORS */
3994 /* If image specification contains symbolic color definitions, add
3995 these to `attrs'. */
3996 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3997 if (CONSP (color_symbols
))
4000 XpmColorSymbol
*xpm_syms
;
4003 attrs
.valuemask
|= XpmColorSymbols
;
4005 /* Count number of symbols. */
4006 attrs
.numsymbols
= 0;
4007 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4010 /* Allocate an XpmColorSymbol array. */
4011 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4012 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4013 bzero (xpm_syms
, size
);
4014 attrs
.colorsymbols
= xpm_syms
;
4016 /* Fill the color symbol array. */
4017 for (tail
= color_symbols
, i
= 0;
4019 ++i
, tail
= XCDR (tail
))
4021 Lisp_Object name
= XCAR (XCAR (tail
));
4022 Lisp_Object color
= XCDR (XCAR (tail
));
4023 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4024 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4025 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4026 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4030 /* Create a pixmap for the image, either from a file, or from a
4031 string buffer containing data in the same format as an XPM file. */
4032 #ifdef ALLOC_XPM_COLORS
4033 xpm_init_color_cache (f
, &attrs
);
4036 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4040 HDC frame_dc
= get_frame_dc (f
);
4041 hdc
= CreateCompatibleDC (frame_dc
);
4042 release_frame_dc (f
, frame_dc
);
4044 #endif /* HAVE_NTGUI */
4046 if (STRINGP (specified_file
))
4048 Lisp_Object file
= x_find_image_file (specified_file
);
4049 if (!STRINGP (file
))
4051 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4056 /* XpmReadFileToPixmap is not available in the Windows port of
4057 libxpm. But XpmReadFileToImage almost does what we want. */
4058 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4059 &xpm_image
, &xpm_mask
,
4062 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4063 SDATA (file
), &img
->pixmap
, &img
->mask
,
4065 #endif /* HAVE_NTGUI */
4069 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4071 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4072 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4073 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4074 &xpm_image
, &xpm_mask
,
4077 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4079 &img
->pixmap
, &img
->mask
,
4081 #endif /* HAVE_NTGUI */
4084 if (rc
== XpmSuccess
)
4086 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4087 img
->colors
= colors_in_color_table (&img
->ncolors
);
4088 #else /* not ALLOC_XPM_COLORS */
4092 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4093 plus some duplicate attributes. */
4094 if (xpm_image
&& xpm_image
->bitmap
)
4096 img
->pixmap
= xpm_image
->bitmap
;
4097 /* XImageFree in libXpm frees XImage struct without destroying
4098 the bitmap, which is what we want. */
4099 fn_XImageFree (xpm_image
);
4101 if (xpm_mask
&& xpm_mask
->bitmap
)
4103 /* The mask appears to be inverted compared with what we expect.
4104 TODO: invert our expectations. See other places where we
4105 have to invert bits because our idea of masks is backwards. */
4107 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4109 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4110 SelectObject (hdc
, old_obj
);
4112 img
->mask
= xpm_mask
->bitmap
;
4113 fn_XImageFree (xpm_mask
);
4118 #endif /* HAVE_NTGUI */
4120 /* Remember allocated colors. */
4121 img
->ncolors
= attrs
.nalloc_pixels
;
4122 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4123 * sizeof *img
->colors
);
4124 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4126 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4127 #ifdef DEBUG_X_COLORS
4128 register_color (img
->colors
[i
]);
4131 #endif /* not ALLOC_XPM_COLORS */
4133 img
->width
= attrs
.width
;
4134 img
->height
= attrs
.height
;
4135 xassert (img
->width
> 0 && img
->height
> 0);
4137 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4139 fn_XpmFreeAttributes (&attrs
);
4141 XpmFreeAttributes (&attrs
);
4142 #endif /* HAVE_NTGUI */
4148 #endif /* HAVE_NTGUI */
4153 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4156 case XpmFileInvalid
:
4157 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4161 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4164 case XpmColorFailed
:
4165 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4169 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4174 #ifdef ALLOC_XPM_COLORS
4175 xpm_free_color_cache ();
4177 return rc
== XpmSuccess
;
4180 #endif /* HAVE_XPM */
4184 /* XPM support functions for Mac OS where libxpm is not available.
4185 Only XPM version 3 (without any extensions) is supported. */
4187 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4188 const unsigned char **, int *));
4189 static Lisp_Object xpm_make_color_table_v
4190 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4191 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4192 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4194 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4195 const unsigned char *, int));
4196 static Lisp_Object xpm_make_color_table_h
4197 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4198 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4199 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4201 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4202 const unsigned char *, int));
4203 static int xpm_str_to_color_key
P_ ((const char *));
4204 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4205 const unsigned char *, const unsigned char *));
4207 /* Tokens returned from xpm_scan. */
4216 /* Scan an XPM data and return a character (< 256) or a token defined
4217 by enum xpm_token above. *S and END are the start (inclusive) and
4218 the end (exclusive) addresses of the data, respectively. Advance
4219 *S while scanning. If token is either XPM_TK_IDENT or
4220 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4221 length of the corresponding token, respectively. */
4224 xpm_scan (s
, end
, beg
, len
)
4225 const unsigned char **s
, *end
, **beg
;
4232 /* Skip white-space. */
4233 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4236 /* gnus-pointer.xpm uses '-' in its identifier.
4237 sb-dir-plus.xpm uses '+' in its identifier. */
4238 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4242 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4245 return XPM_TK_IDENT
;
4250 while (*s
< end
&& **s
!= '"')
4255 return XPM_TK_STRING
;
4259 if (*s
< end
&& **s
== '*')
4261 /* C-style comment. */
4265 while (*s
< end
&& *(*s
)++ != '*')
4268 while (*s
< end
&& **s
!= '/');
4282 /* Functions for color table lookup in XPM data. A Key is a string
4283 specifying the color of each pixel in XPM data. A value is either
4284 an integer that specifies a pixel color, Qt that specifies
4285 transparency, or Qnil for the unspecified color. If the length of
4286 the key string is one, a vector is used as a table. Otherwise, a
4287 hash table is used. */
4290 xpm_make_color_table_v (put_func
, get_func
)
4291 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4292 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4294 *put_func
= xpm_put_color_table_v
;
4295 *get_func
= xpm_get_color_table_v
;
4296 return Fmake_vector (make_number (256), Qnil
);
4300 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4301 Lisp_Object color_table
;
4302 const unsigned char *chars_start
;
4306 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4310 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4311 Lisp_Object color_table
;
4312 const unsigned char *chars_start
;
4315 return XVECTOR (color_table
)->contents
[*chars_start
];
4319 xpm_make_color_table_h (put_func
, get_func
)
4320 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4321 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4323 *put_func
= xpm_put_color_table_h
;
4324 *get_func
= xpm_get_color_table_h
;
4325 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4326 make_float (DEFAULT_REHASH_SIZE
),
4327 make_float (DEFAULT_REHASH_THRESHOLD
),
4332 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4333 Lisp_Object color_table
;
4334 const unsigned char *chars_start
;
4338 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4340 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4342 hash_lookup (table
, chars
, &hash_code
);
4343 hash_put (table
, chars
, color
, hash_code
);
4347 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4348 Lisp_Object color_table
;
4349 const unsigned char *chars_start
;
4352 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4353 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4356 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4359 enum xpm_color_key
{
4367 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4370 xpm_str_to_color_key (s
)
4376 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4378 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4384 xpm_load_image (f
, img
, contents
, end
)
4387 const unsigned char *contents
, *end
;
4389 const unsigned char *s
= contents
, *beg
, *str
;
4390 unsigned char buffer
[BUFSIZ
];
4391 int width
, height
, x
, y
;
4392 int num_colors
, chars_per_pixel
;
4394 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4395 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4396 Lisp_Object frame
, color_symbols
, color_table
;
4397 int best_key
, have_mask
= 0;
4398 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4401 LA1 = xpm_scan (&s, end, &beg, &len)
4403 #define expect(TOKEN) \
4404 if (LA1 != (TOKEN)) \
4409 #define expect_ident(IDENT) \
4410 if (LA1 == XPM_TK_IDENT \
4411 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4416 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4420 expect_ident ("static");
4421 expect_ident ("char");
4423 expect (XPM_TK_IDENT
);
4428 expect (XPM_TK_STRING
);
4431 memcpy (buffer
, beg
, len
);
4433 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4434 &num_colors
, &chars_per_pixel
) != 4
4435 || width
<= 0 || height
<= 0
4436 || num_colors
<= 0 || chars_per_pixel
<= 0)
4439 if (!check_image_size (f
, width
, height
))
4441 image_error ("Invalid image size", Qnil
, Qnil
);
4447 XSETFRAME (frame
, f
);
4448 if (!NILP (Fxw_display_color_p (frame
)))
4449 best_key
= XPM_COLOR_KEY_C
;
4450 else if (!NILP (Fx_display_grayscale_p (frame
)))
4451 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4452 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4454 best_key
= XPM_COLOR_KEY_M
;
4456 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4457 if (chars_per_pixel
== 1)
4458 color_table
= xpm_make_color_table_v (&put_color_table
,
4461 color_table
= xpm_make_color_table_h (&put_color_table
,
4464 while (num_colors
-- > 0)
4466 unsigned char *color
, *max_color
;
4467 int key
, next_key
, max_key
= 0;
4468 Lisp_Object symbol_color
= Qnil
, color_val
;
4471 expect (XPM_TK_STRING
);
4472 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4474 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4475 buffer
[len
- chars_per_pixel
] = '\0';
4477 str
= strtok (buffer
, " \t");
4480 key
= xpm_str_to_color_key (str
);
4485 color
= strtok (NULL
, " \t");
4489 while ((str
= strtok (NULL
, " \t")) != NULL
)
4491 next_key
= xpm_str_to_color_key (str
);
4494 color
[strlen (color
)] = ' ';
4497 if (key
== XPM_COLOR_KEY_S
)
4499 if (NILP (symbol_color
))
4500 symbol_color
= build_string (color
);
4502 else if (max_key
< key
&& key
<= best_key
)
4512 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4514 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4516 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4518 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4520 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4522 color_val
= make_number (cdef
.pixel
);
4525 if (NILP (color_val
) && max_key
> 0)
4527 if (xstricmp (max_color
, "None") == 0)
4529 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4530 color_val
= make_number (cdef
.pixel
);
4532 if (!NILP (color_val
))
4533 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4538 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4539 &ximg
, &img
->pixmap
)
4540 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4541 &mask_img
, &img
->mask
))
4543 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4547 for (y
= 0; y
< height
; y
++)
4549 expect (XPM_TK_STRING
);
4551 if (len
< width
* chars_per_pixel
)
4553 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4555 Lisp_Object color_val
=
4556 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4558 XPutPixel (ximg
, x
, y
,
4559 (INTEGERP (color_val
) ? XINT (color_val
)
4560 : FRAME_FOREGROUND_PIXEL (f
)));
4561 XPutPixel (mask_img
, x
, y
,
4562 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4563 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4570 img
->height
= height
;
4572 /* Maybe fill in the background field while we have ximg handy. */
4573 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4574 IMAGE_BACKGROUND (img
, f
, ximg
);
4576 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4577 x_destroy_x_image (ximg
);
4580 /* Fill in the background_transparent field while we have the
4582 image_background_transparent (img
, f
, mask_img
);
4584 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4585 x_destroy_x_image (mask_img
);
4589 x_destroy_x_image (mask_img
);
4590 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4591 img
->mask
= NO_PIXMAP
;
4597 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4599 x_destroy_x_image (ximg
);
4600 x_destroy_x_image (mask_img
);
4601 x_clear_image (f
, img
);
4615 Lisp_Object file_name
;
4617 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4618 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4619 if (STRINGP (file_name
))
4622 unsigned char *contents
;
4624 struct gcpro gcpro1
;
4626 file
= x_find_image_file (file_name
);
4628 if (!STRINGP (file
))
4630 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4635 contents
= slurp_file (SDATA (file
), &size
);
4636 if (contents
== NULL
)
4638 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4643 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4651 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4652 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4653 SDATA (data
) + SBYTES (data
));
4663 /***********************************************************************
4665 ***********************************************************************/
4667 #ifdef COLOR_TABLE_SUPPORT
4669 /* An entry in the color table mapping an RGB color to a pixel color. */
4674 unsigned long pixel
;
4676 /* Next in color table collision list. */
4677 struct ct_color
*next
;
4680 /* The bucket vector size to use. Must be prime. */
4684 /* Value is a hash of the RGB color given by R, G, and B. */
4686 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4688 /* The color hash table. */
4690 struct ct_color
**ct_table
;
4692 /* Number of entries in the color table. */
4694 int ct_colors_allocated
;
4696 /* Initialize the color table. */
4701 int size
= CT_SIZE
* sizeof (*ct_table
);
4702 ct_table
= (struct ct_color
**) xmalloc (size
);
4703 bzero (ct_table
, size
);
4704 ct_colors_allocated
= 0;
4708 /* Free memory associated with the color table. */
4714 struct ct_color
*p
, *next
;
4716 for (i
= 0; i
< CT_SIZE
; ++i
)
4717 for (p
= ct_table
[i
]; p
; p
= next
)
4728 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4729 entry for that color already is in the color table, return the
4730 pixel color of that entry. Otherwise, allocate a new color for R,
4731 G, B, and make an entry in the color table. */
4733 static unsigned long
4734 lookup_rgb_color (f
, r
, g
, b
)
4738 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4739 int i
= hash
% CT_SIZE
;
4741 Display_Info
*dpyinfo
;
4743 /* Handle TrueColor visuals specially, which improves performance by
4744 two orders of magnitude. Freeing colors on TrueColor visuals is
4745 a nop, and pixel colors specify RGB values directly. See also
4746 the Xlib spec, chapter 3.1. */
4747 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4748 if (dpyinfo
->red_bits
> 0)
4750 unsigned long pr
, pg
, pb
;
4752 /* Apply gamma-correction like normal color allocation does. */
4756 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4757 gamma_correct (f
, &color
);
4758 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4761 /* Scale down RGB values to the visual's bits per RGB, and shift
4762 them to the right position in the pixel color. Note that the
4763 original RGB values are 16-bit values, as usual in X. */
4764 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4765 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4766 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4768 /* Assemble the pixel color. */
4769 return pr
| pg
| pb
;
4772 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4773 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4779 #ifdef HAVE_X_WINDOWS
4788 cmap
= FRAME_X_COLORMAP (f
);
4789 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4792 ++ct_colors_allocated
;
4793 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4797 p
->pixel
= color
.pixel
;
4798 p
->next
= ct_table
[i
];
4802 return FRAME_FOREGROUND_PIXEL (f
);
4807 color
= PALETTERGB (r
, g
, b
);
4809 color
= RGB_TO_ULONG (r
, g
, b
);
4810 #endif /* HAVE_NTGUI */
4811 ++ct_colors_allocated
;
4812 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4817 p
->next
= ct_table
[i
];
4819 #endif /* HAVE_X_WINDOWS */
4827 /* Look up pixel color PIXEL which is used on frame F in the color
4828 table. If not already present, allocate it. Value is PIXEL. */
4830 static unsigned long
4831 lookup_pixel_color (f
, pixel
)
4833 unsigned long pixel
;
4835 int i
= pixel
% CT_SIZE
;
4838 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4839 if (p
->pixel
== pixel
)
4848 #ifdef HAVE_X_WINDOWS
4849 cmap
= FRAME_X_COLORMAP (f
);
4850 color
.pixel
= pixel
;
4851 x_query_color (f
, &color
);
4852 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4855 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4856 color
.pixel
= pixel
;
4857 XQueryColor (NULL
, cmap
, &color
);
4858 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4860 #endif /* HAVE_X_WINDOWS */
4864 ++ct_colors_allocated
;
4866 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4871 p
->next
= ct_table
[i
];
4875 return FRAME_FOREGROUND_PIXEL (f
);
4881 /* Value is a vector of all pixel colors contained in the color table,
4882 allocated via xmalloc. Set *N to the number of colors. */
4884 static unsigned long *
4885 colors_in_color_table (n
)
4890 unsigned long *colors
;
4892 if (ct_colors_allocated
== 0)
4899 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4901 *n
= ct_colors_allocated
;
4903 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4904 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4905 colors
[j
++] = p
->pixel
;
4911 #else /* COLOR_TABLE_SUPPORT */
4913 static unsigned long
4914 lookup_rgb_color (f
, r
, g
, b
)
4918 unsigned long pixel
;
4921 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4922 gamma_correct (f
, &pixel
);
4926 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4927 #endif /* HAVE_NTGUI */
4936 #endif /* COLOR_TABLE_SUPPORT */
4939 /***********************************************************************
4941 ***********************************************************************/
4943 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4944 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4945 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4948 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4949 #endif /* HAVE_NTGUI */
4951 /* Non-zero means draw a cross on images having `:conversion
4954 int cross_disabled_images
;
4956 /* Edge detection matrices for different edge-detection
4959 static int emboss_matrix
[9] = {
4961 2, -1, 0, /* y - 1 */
4963 0, 1, -2 /* y + 1 */
4966 static int laplace_matrix
[9] = {
4968 1, 0, 0, /* y - 1 */
4970 0, 0, -1 /* y + 1 */
4973 /* Value is the intensity of the color whose red/green/blue values
4976 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4979 /* On frame F, return an array of XColor structures describing image
4980 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4981 non-zero means also fill the red/green/blue members of the XColor
4982 structures. Value is a pointer to the array of XColors structures,
4983 allocated with xmalloc; it must be freed by the caller. */
4986 x_to_xcolors (f
, img
, rgb_p
)
4993 XImagePtr_or_DC ximg
;
4997 #endif /* HAVE_NTGUI */
4999 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5002 /* Get the X image IMG->pixmap. */
5003 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5004 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5006 /* Load the image into a memory device context. */
5007 hdc
= get_frame_dc (f
);
5008 ximg
= CreateCompatibleDC (hdc
);
5009 release_frame_dc (f
, hdc
);
5010 prev
= SelectObject (ximg
, img
->pixmap
);
5011 #endif /* HAVE_NTGUI */
5013 /* Fill the `pixel' members of the XColor array. I wished there
5014 were an easy and portable way to circumvent XGetPixel. */
5016 for (y
= 0; y
< img
->height
; ++y
)
5020 #ifdef HAVE_X_WINDOWS
5021 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5022 p
->pixel
= XGetPixel (ximg
, x
, y
);
5024 x_query_colors (f
, row
, img
->width
);
5028 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5030 /* W32_TODO: palette support needed here? */
5031 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5035 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5036 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5037 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5040 p
->red
= 256 * GetRValue (p
->pixel
);
5041 p
->green
= 256 * GetGValue (p
->pixel
);
5042 p
->blue
= 256 * GetBValue (p
->pixel
);
5043 #endif /* HAVE_NTGUI */
5046 #endif /* HAVE_X_WINDOWS */
5049 Destroy_Image (ximg
, prev
);
5056 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5057 created with CreateDIBSection, with the pointer to the bit values
5058 stored in ximg->data. */
5060 static void XPutPixel (ximg
, x
, y
, color
)
5065 int width
= ximg
->info
.bmiHeader
.biWidth
;
5066 int height
= ximg
->info
.bmiHeader
.biHeight
;
5067 unsigned char * pixel
;
5069 /* True color images. */
5070 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5072 int rowbytes
= width
* 3;
5073 /* Ensure scanlines are aligned on 4 byte boundaries. */
5075 rowbytes
+= 4 - (rowbytes
% 4);
5077 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5078 /* Windows bitmaps are in BGR order. */
5079 *pixel
= GetBValue (color
);
5080 *(pixel
+ 1) = GetGValue (color
);
5081 *(pixel
+ 2) = GetRValue (color
);
5083 /* Monochrome images. */
5084 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5086 int rowbytes
= width
/ 8;
5087 /* Ensure scanlines are aligned on 4 byte boundaries. */
5089 rowbytes
+= 4 - (rowbytes
% 4);
5090 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5091 /* Filter out palette info. */
5092 if (color
& 0x00ffffff)
5093 *pixel
= *pixel
| (1 << x
% 8);
5095 *pixel
= *pixel
& ~(1 << x
% 8);
5098 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5101 #endif /* HAVE_NTGUI */
5103 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5104 RGB members are set. F is the frame on which this all happens.
5105 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5108 x_from_xcolors (f
, img
, colors
)
5118 init_color_table ();
5120 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5123 for (y
= 0; y
< img
->height
; ++y
)
5124 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5126 unsigned long pixel
;
5127 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5128 XPutPixel (oimg
, x
, y
, pixel
);
5132 x_clear_image_1 (f
, img
, 1, 0, 1);
5134 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5135 x_destroy_x_image (oimg
);
5136 img
->pixmap
= pixmap
;
5137 #ifdef COLOR_TABLE_SUPPORT
5138 img
->colors
= colors_in_color_table (&img
->ncolors
);
5139 free_color_table ();
5140 #endif /* COLOR_TABLE_SUPPORT */
5144 /* On frame F, perform edge-detection on image IMG.
5146 MATRIX is a nine-element array specifying the transformation
5147 matrix. See emboss_matrix for an example.
5149 COLOR_ADJUST is a color adjustment added to each pixel of the
5153 x_detect_edges (f
, img
, matrix
, color_adjust
)
5156 int matrix
[9], color_adjust
;
5158 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5162 for (i
= sum
= 0; i
< 9; ++i
)
5163 sum
+= abs (matrix
[i
]);
5165 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5167 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5169 for (y
= 0; y
< img
->height
; ++y
)
5171 p
= COLOR (new, 0, y
);
5172 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5173 p
= COLOR (new, img
->width
- 1, y
);
5174 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5177 for (x
= 1; x
< img
->width
- 1; ++x
)
5179 p
= COLOR (new, x
, 0);
5180 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5181 p
= COLOR (new, x
, img
->height
- 1);
5182 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5185 for (y
= 1; y
< img
->height
- 1; ++y
)
5187 p
= COLOR (new, 1, y
);
5189 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5191 int r
, g
, b
, y1
, x1
;
5194 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5195 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5198 XColor
*t
= COLOR (colors
, x1
, y1
);
5199 r
+= matrix
[i
] * t
->red
;
5200 g
+= matrix
[i
] * t
->green
;
5201 b
+= matrix
[i
] * t
->blue
;
5204 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5205 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5206 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5207 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5212 x_from_xcolors (f
, img
, new);
5218 /* Perform the pre-defined `emboss' edge-detection on image IMG
5226 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5230 /* Transform image IMG which is used on frame F with a Laplace
5231 edge-detection algorithm. The result is an image that can be used
5232 to draw disabled buttons, for example. */
5239 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5243 /* Perform edge-detection on image IMG on frame F, with specified
5244 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5246 MATRIX must be either
5248 - a list of at least 9 numbers in row-major form
5249 - a vector of at least 9 numbers
5251 COLOR_ADJUST nil means use a default; otherwise it must be a
5255 x_edge_detection (f
, img
, matrix
, color_adjust
)
5258 Lisp_Object matrix
, color_adjust
;
5266 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5267 ++i
, matrix
= XCDR (matrix
))
5268 trans
[i
] = XFLOATINT (XCAR (matrix
));
5270 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5272 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5273 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5276 if (NILP (color_adjust
))
5277 color_adjust
= make_number (0xffff / 2);
5279 if (i
== 9 && NUMBERP (color_adjust
))
5280 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5284 /* Transform image IMG on frame F so that it looks disabled. */
5287 x_disable_image (f
, img
)
5291 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5293 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5295 int n_planes
= dpyinfo
->n_planes
;
5296 #endif /* HAVE_NTGUI */
5300 /* Color (or grayscale). Convert to gray, and equalize. Just
5301 drawing such images with a stipple can look very odd, so
5302 we're using this method instead. */
5303 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5305 const int h
= 15000;
5306 const int l
= 30000;
5308 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5312 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5313 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5314 p
->red
= p
->green
= p
->blue
= i2
;
5317 x_from_xcolors (f
, img
, colors
);
5320 /* Draw a cross over the disabled image, if we must or if we
5322 if (n_planes
< 2 || cross_disabled_images
)
5325 Display
*dpy
= FRAME_X_DISPLAY (f
);
5329 #define MaskForeground(f) PIX_MASK_DRAW
5331 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5334 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5335 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5336 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5337 img
->width
- 1, img
->height
- 1);
5338 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5344 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5345 XSetForeground (dpy
, gc
, MaskForeground (f
));
5346 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5347 img
->width
- 1, img
->height
- 1);
5348 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5356 hdc
= get_frame_dc (f
);
5357 bmpdc
= CreateCompatibleDC (hdc
);
5358 release_frame_dc (f
, hdc
);
5360 prev
= SelectObject (bmpdc
, img
->pixmap
);
5362 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5363 MoveToEx (bmpdc
, 0, 0, NULL
);
5364 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5365 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5366 LineTo (bmpdc
, img
->width
- 1, 0);
5370 SelectObject (bmpdc
, img
->mask
);
5371 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5372 MoveToEx (bmpdc
, 0, 0, NULL
);
5373 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5374 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5375 LineTo (bmpdc
, img
->width
- 1, 0);
5377 SelectObject (bmpdc
, prev
);
5379 #endif /* HAVE_NTGUI */
5384 /* Build a mask for image IMG which is used on frame F. FILE is the
5385 name of an image file, for error messages. HOW determines how to
5386 determine the background color of IMG. If it is a list '(R G B)',
5387 with R, G, and B being integers >= 0, take that as the color of the
5388 background. Otherwise, determine the background color of IMG
5389 heuristically. Value is non-zero if successful. */
5392 x_build_heuristic_mask (f
, img
, how
)
5397 XImagePtr_or_DC ximg
;
5405 #endif /* HAVE_NTGUI */
5406 int x
, y
, rc
, use_img_background
;
5407 unsigned long bg
= 0;
5411 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5412 img
->mask
= NO_PIXMAP
;
5413 img
->background_transparent_valid
= 0;
5417 /* Create an image and pixmap serving as mask. */
5418 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5419 &mask_img
, &img
->mask
);
5423 /* Get the X image of IMG->pixmap. */
5424 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5425 img
->width
, img
->height
,
5428 /* Create the bit array serving as mask. */
5429 row_width
= (img
->width
+ 7) / 8;
5430 mask_img
= xmalloc (row_width
* img
->height
);
5431 bzero (mask_img
, row_width
* img
->height
);
5433 /* Create a memory device context for IMG->pixmap. */
5434 frame_dc
= get_frame_dc (f
);
5435 ximg
= CreateCompatibleDC (frame_dc
);
5436 release_frame_dc (f
, frame_dc
);
5437 prev
= SelectObject (ximg
, img
->pixmap
);
5438 #endif /* HAVE_NTGUI */
5440 /* Determine the background color of ximg. If HOW is `(R G B)'
5441 take that as color. Otherwise, use the image's background color. */
5442 use_img_background
= 1;
5448 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5450 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5454 if (i
== 3 && NILP (how
))
5456 char color_name
[30];
5457 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5460 0x00ffffff & /* Filter out palette info. */
5461 #endif /* HAVE_NTGUI */
5462 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5463 use_img_background
= 0;
5467 if (use_img_background
)
5468 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5470 /* Set all bits in mask_img to 1 whose color in ximg is different
5471 from the background color bg. */
5473 for (y
= 0; y
< img
->height
; ++y
)
5474 for (x
= 0; x
< img
->width
; ++x
)
5475 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5476 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5478 /* Fill in the background_transparent field while we have the mask handy. */
5479 image_background_transparent (img
, f
, mask_img
);
5481 /* Put mask_img into img->mask. */
5482 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5483 x_destroy_x_image (mask_img
);
5486 for (y
= 0; y
< img
->height
; ++y
)
5487 for (x
= 0; x
< img
->width
; ++x
)
5489 COLORREF p
= GetPixel (ximg
, x
, y
);
5491 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5494 /* Create the mask image. */
5495 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5497 /* Fill in the background_transparent field while we have the mask handy. */
5498 SelectObject (ximg
, img
->mask
);
5499 image_background_transparent (img
, f
, ximg
);
5501 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5503 #endif /* HAVE_NTGUI */
5505 Destroy_Image (ximg
, prev
);
5511 /***********************************************************************
5512 PBM (mono, gray, color)
5513 ***********************************************************************/
5515 static int pbm_image_p
P_ ((Lisp_Object object
));
5516 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5517 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5519 /* The symbol `pbm' identifying images of this type. */
5523 /* Indices of image specification fields in gs_format, below. */
5525 enum pbm_keyword_index
5541 /* Vector of image_keyword structures describing the format
5542 of valid user-defined image specifications. */
5544 static struct image_keyword pbm_format
[PBM_LAST
] =
5546 {":type", IMAGE_SYMBOL_VALUE
, 1},
5547 {":file", IMAGE_STRING_VALUE
, 0},
5548 {":data", IMAGE_STRING_VALUE
, 0},
5549 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5550 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5551 {":relief", IMAGE_INTEGER_VALUE
, 0},
5552 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5553 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5554 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5555 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5556 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5559 /* Structure describing the image type `pbm'. */
5561 static struct image_type pbm_type
=
5571 /* Return non-zero if OBJECT is a valid PBM image specification. */
5574 pbm_image_p (object
)
5577 struct image_keyword fmt
[PBM_LAST
];
5579 bcopy (pbm_format
, fmt
, sizeof fmt
);
5581 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5584 /* Must specify either :data or :file. */
5585 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5589 /* Scan a decimal number from *S and return it. Advance *S while
5590 reading the number. END is the end of the string. Value is -1 at
5594 pbm_scan_number (s
, end
)
5595 unsigned char **s
, *end
;
5597 int c
= 0, val
= -1;
5601 /* Skip white-space. */
5602 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5607 /* Skip comment to end of line. */
5608 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5611 else if (isdigit (c
))
5613 /* Read decimal number. */
5615 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5616 val
= 10 * val
+ c
- '0';
5628 #if 0 /* Unused. ++kfs */
5630 /* Read FILE into memory. Value is a pointer to a buffer allocated
5631 with xmalloc holding FILE's contents. Value is null if an error
5632 occurred. *SIZE is set to the size of the file. */
5635 pbm_read_file (file
, size
)
5643 if (stat (SDATA (file
), &st
) == 0
5644 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5645 && (buf
= (char *) xmalloc (st
.st_size
),
5646 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5665 #endif /* HAVE_NTGUI */
5667 /* Load PBM image IMG for use on frame F. */
5675 int width
, height
, max_color_idx
= 0;
5677 Lisp_Object file
, specified_file
;
5678 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5679 struct gcpro gcpro1
;
5680 unsigned char *contents
= NULL
;
5681 unsigned char *end
, *p
;
5684 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5688 if (STRINGP (specified_file
))
5690 file
= x_find_image_file (specified_file
);
5691 if (!STRINGP (file
))
5693 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5698 contents
= slurp_file (SDATA (file
), &size
);
5699 if (contents
== NULL
)
5701 image_error ("Error reading `%s'", file
, Qnil
);
5707 end
= contents
+ size
;
5712 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5714 end
= p
+ SBYTES (data
);
5717 /* Check magic number. */
5718 if (end
- p
< 2 || *p
++ != 'P')
5720 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5730 raw_p
= 0, type
= PBM_MONO
;
5734 raw_p
= 0, type
= PBM_GRAY
;
5738 raw_p
= 0, type
= PBM_COLOR
;
5742 raw_p
= 1, type
= PBM_MONO
;
5746 raw_p
= 1, type
= PBM_GRAY
;
5750 raw_p
= 1, type
= PBM_COLOR
;
5754 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5758 /* Read width, height, maximum color-component. Characters
5759 starting with `#' up to the end of a line are ignored. */
5760 width
= pbm_scan_number (&p
, end
);
5761 height
= pbm_scan_number (&p
, end
);
5763 if (type
!= PBM_MONO
)
5765 max_color_idx
= pbm_scan_number (&p
, end
);
5766 if (raw_p
&& max_color_idx
> 255)
5767 max_color_idx
= 255;
5770 if (!check_image_size (f
, width
, height
)
5771 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5774 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5775 &ximg
, &img
->pixmap
))
5778 /* Initialize the color hash table. */
5779 init_color_table ();
5781 if (type
== PBM_MONO
)
5784 struct image_keyword fmt
[PBM_LAST
];
5785 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5786 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5788 /* Parse the image specification. */
5789 bcopy (pbm_format
, fmt
, sizeof fmt
);
5790 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5792 /* Get foreground and background colors, maybe allocate colors. */
5793 if (fmt
[PBM_FOREGROUND
].count
5794 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5795 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5796 if (fmt
[PBM_BACKGROUND
].count
5797 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5799 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5800 img
->background
= bg
;
5801 img
->background_valid
= 1;
5804 for (y
= 0; y
< height
; ++y
)
5805 for (x
= 0; x
< width
; ++x
)
5813 x_destroy_x_image (ximg
);
5814 x_clear_image (f
, img
);
5815 image_error ("Invalid image size in image `%s'",
5825 g
= pbm_scan_number (&p
, end
);
5827 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5833 && ((type
== PBM_GRAY
)
5834 ? (p
+ height
* width
> end
)
5835 : (p
+ 3 * height
* width
> end
)))
5837 x_destroy_x_image (ximg
);
5838 x_clear_image (f
, img
);
5839 image_error ("Invalid image size in image `%s'",
5844 for (y
= 0; y
< height
; ++y
)
5845 for (x
= 0; x
< width
; ++x
)
5849 if (type
== PBM_GRAY
)
5850 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5859 r
= pbm_scan_number (&p
, end
);
5860 g
= pbm_scan_number (&p
, end
);
5861 b
= pbm_scan_number (&p
, end
);
5864 if (r
< 0 || g
< 0 || b
< 0)
5866 x_destroy_x_image (ximg
);
5867 image_error ("Invalid pixel value in image `%s'",
5872 /* RGB values are now in the range 0..max_color_idx.
5873 Scale this to the range 0..0xffff supported by X. */
5874 r
= (double) r
* 65535 / max_color_idx
;
5875 g
= (double) g
* 65535 / max_color_idx
;
5876 b
= (double) b
* 65535 / max_color_idx
;
5877 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5881 #ifdef COLOR_TABLE_SUPPORT
5882 /* Store in IMG->colors the colors allocated for the image, and
5883 free the color table. */
5884 img
->colors
= colors_in_color_table (&img
->ncolors
);
5885 free_color_table ();
5886 #endif /* COLOR_TABLE_SUPPORT */
5889 img
->height
= height
;
5891 /* Maybe fill in the background field while we have ximg handy. */
5893 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5894 /* Casting avoids a GCC warning. */
5895 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5897 /* Put the image into a pixmap. */
5898 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5899 x_destroy_x_image (ximg
);
5901 /* X and W32 versions did it here, MAC version above. ++kfs
5903 img->height = height; */
5911 /***********************************************************************
5913 ***********************************************************************/
5915 #if defined (HAVE_PNG) || defined (MAC_OS)
5917 /* Function prototypes. */
5919 static int png_image_p
P_ ((Lisp_Object object
));
5920 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5922 /* The symbol `png' identifying images of this type. */
5926 /* Indices of image specification fields in png_format, below. */
5928 enum png_keyword_index
5943 /* Vector of image_keyword structures describing the format
5944 of valid user-defined image specifications. */
5946 static struct image_keyword png_format
[PNG_LAST
] =
5948 {":type", IMAGE_SYMBOL_VALUE
, 1},
5949 {":data", IMAGE_STRING_VALUE
, 0},
5950 {":file", IMAGE_STRING_VALUE
, 0},
5951 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5952 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5953 {":relief", IMAGE_INTEGER_VALUE
, 0},
5954 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5955 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5956 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5957 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5960 /* Structure describing the image type `png'. */
5962 static struct image_type png_type
=
5971 /* Return non-zero if OBJECT is a valid PNG image specification. */
5974 png_image_p (object
)
5977 struct image_keyword fmt
[PNG_LAST
];
5978 bcopy (png_format
, fmt
, sizeof fmt
);
5980 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5983 /* Must specify either the :data or :file keyword. */
5984 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5987 #endif /* HAVE_PNG || MAC_OS */
5992 #if defined HAVE_LIBPNG_PNG_H
5993 # include <libpng/png.h>
5999 /* PNG library details. */
6001 DEF_IMGLIB_FN (png_get_io_ptr
);
6002 DEF_IMGLIB_FN (png_check_sig
);
6003 DEF_IMGLIB_FN (png_create_read_struct
);
6004 DEF_IMGLIB_FN (png_create_info_struct
);
6005 DEF_IMGLIB_FN (png_destroy_read_struct
);
6006 DEF_IMGLIB_FN (png_set_read_fn
);
6007 DEF_IMGLIB_FN (png_set_sig_bytes
);
6008 DEF_IMGLIB_FN (png_read_info
);
6009 DEF_IMGLIB_FN (png_get_IHDR
);
6010 DEF_IMGLIB_FN (png_get_valid
);
6011 DEF_IMGLIB_FN (png_set_strip_16
);
6012 DEF_IMGLIB_FN (png_set_expand
);
6013 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6014 DEF_IMGLIB_FN (png_set_background
);
6015 DEF_IMGLIB_FN (png_get_bKGD
);
6016 DEF_IMGLIB_FN (png_read_update_info
);
6017 DEF_IMGLIB_FN (png_get_channels
);
6018 DEF_IMGLIB_FN (png_get_rowbytes
);
6019 DEF_IMGLIB_FN (png_read_image
);
6020 DEF_IMGLIB_FN (png_read_end
);
6021 DEF_IMGLIB_FN (png_error
);
6024 init_png_functions (Lisp_Object libraries
)
6028 /* Try loading libpng under probable names. */
6029 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6032 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6033 LOAD_IMGLIB_FN (library
, png_check_sig
);
6034 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6035 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6036 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6037 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6038 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6039 LOAD_IMGLIB_FN (library
, png_read_info
);
6040 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6041 LOAD_IMGLIB_FN (library
, png_get_valid
);
6042 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6043 LOAD_IMGLIB_FN (library
, png_set_expand
);
6044 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6045 LOAD_IMGLIB_FN (library
, png_set_background
);
6046 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6047 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6048 LOAD_IMGLIB_FN (library
, png_get_channels
);
6049 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6050 LOAD_IMGLIB_FN (library
, png_read_image
);
6051 LOAD_IMGLIB_FN (library
, png_read_end
);
6052 LOAD_IMGLIB_FN (library
, png_error
);
6057 #define fn_png_get_io_ptr png_get_io_ptr
6058 #define fn_png_check_sig png_check_sig
6059 #define fn_png_create_read_struct png_create_read_struct
6060 #define fn_png_create_info_struct png_create_info_struct
6061 #define fn_png_destroy_read_struct png_destroy_read_struct
6062 #define fn_png_set_read_fn png_set_read_fn
6063 #define fn_png_set_sig_bytes png_set_sig_bytes
6064 #define fn_png_read_info png_read_info
6065 #define fn_png_get_IHDR png_get_IHDR
6066 #define fn_png_get_valid png_get_valid
6067 #define fn_png_set_strip_16 png_set_strip_16
6068 #define fn_png_set_expand png_set_expand
6069 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6070 #define fn_png_set_background png_set_background
6071 #define fn_png_get_bKGD png_get_bKGD
6072 #define fn_png_read_update_info png_read_update_info
6073 #define fn_png_get_channels png_get_channels
6074 #define fn_png_get_rowbytes png_get_rowbytes
6075 #define fn_png_read_image png_read_image
6076 #define fn_png_read_end png_read_end
6077 #define fn_png_error png_error
6079 #endif /* HAVE_NTGUI */
6081 /* Error and warning handlers installed when the PNG library
6085 my_png_error (png_ptr
, msg
)
6086 png_struct
*png_ptr
;
6089 xassert (png_ptr
!= NULL
);
6090 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6091 longjmp (png_ptr
->jmpbuf
, 1);
6096 my_png_warning (png_ptr
, msg
)
6097 png_struct
*png_ptr
;
6100 xassert (png_ptr
!= NULL
);
6101 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6104 /* Memory source for PNG decoding. */
6106 struct png_memory_storage
6108 unsigned char *bytes
; /* The data */
6109 size_t len
; /* How big is it? */
6110 int index
; /* Where are we? */
6114 /* Function set as reader function when reading PNG image from memory.
6115 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6116 bytes from the input to DATA. */
6119 png_read_from_memory (png_ptr
, data
, length
)
6120 png_structp png_ptr
;
6124 struct png_memory_storage
*tbr
6125 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6127 if (length
> tbr
->len
- tbr
->index
)
6128 fn_png_error (png_ptr
, "Read error");
6130 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6131 tbr
->index
= tbr
->index
+ length
;
6135 /* Function set as reader function when reading PNG image from a file.
6136 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6137 bytes from the input to DATA. */
6140 png_read_from_file (png_ptr
, data
, length
)
6141 png_structp png_ptr
;
6145 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6147 if (fread (data
, 1, length
, fp
) < length
)
6148 fn_png_error (png_ptr
, "Read error");
6152 /* Load PNG image IMG for use on frame F. Value is non-zero if
6160 Lisp_Object file
, specified_file
;
6161 Lisp_Object specified_data
;
6163 XImagePtr ximg
, mask_img
= NULL
;
6164 struct gcpro gcpro1
;
6165 png_struct
*png_ptr
= NULL
;
6166 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6167 FILE *volatile fp
= NULL
;
6169 png_byte
* volatile pixels
= NULL
;
6170 png_byte
** volatile rows
= NULL
;
6171 png_uint_32 width
, height
;
6172 int bit_depth
, color_type
, interlace_type
;
6174 png_uint_32 row_bytes
;
6176 double screen_gamma
;
6177 struct png_memory_storage tbr
; /* Data to be read */
6179 /* Find out what file to load. */
6180 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6181 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6185 if (NILP (specified_data
))
6187 file
= x_find_image_file (specified_file
);
6188 if (!STRINGP (file
))
6190 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6195 /* Open the image file. */
6196 fp
= fopen (SDATA (file
), "rb");
6199 image_error ("Cannot open image file `%s'", file
, Qnil
);
6204 /* Check PNG signature. */
6205 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6206 || !fn_png_check_sig (sig
, sizeof sig
))
6208 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6216 /* Read from memory. */
6217 tbr
.bytes
= SDATA (specified_data
);
6218 tbr
.len
= SBYTES (specified_data
);
6221 /* Check PNG signature. */
6222 if (tbr
.len
< sizeof sig
6223 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6225 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6230 /* Need to skip past the signature. */
6231 tbr
.bytes
+= sizeof (sig
);
6234 /* Initialize read and info structs for PNG lib. Casting return
6235 value avoids a GCC warning on W32. */
6236 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6241 if (fp
) fclose (fp
);
6246 /* Casting return value avoids a GCC warning on W32. */
6247 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6250 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6251 if (fp
) fclose (fp
);
6256 /* Casting return value avoids a GCC warning on W32. */
6257 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6260 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6261 if (fp
) fclose (fp
);
6266 /* Set error jump-back. We come back here when the PNG library
6267 detects an error. */
6268 if (setjmp (png_ptr
->jmpbuf
))
6272 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6275 if (fp
) fclose (fp
);
6280 /* Read image info. */
6281 if (!NILP (specified_data
))
6282 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6284 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6286 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6287 fn_png_read_info (png_ptr
, info_ptr
);
6288 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6289 &interlace_type
, NULL
, NULL
);
6291 if (!check_image_size (f
, width
, height
))
6294 /* If image contains simply transparency data, we prefer to
6295 construct a clipping mask. */
6296 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6301 /* This function is easier to write if we only have to handle
6302 one data format: RGB or RGBA with 8 bits per channel. Let's
6303 transform other formats into that format. */
6305 /* Strip more than 8 bits per channel. */
6306 if (bit_depth
== 16)
6307 fn_png_set_strip_16 (png_ptr
);
6309 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6311 fn_png_set_expand (png_ptr
);
6313 /* Convert grayscale images to RGB. */
6314 if (color_type
== PNG_COLOR_TYPE_GRAY
6315 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6316 fn_png_set_gray_to_rgb (png_ptr
);
6318 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
6320 #if 0 /* Avoid double gamma correction for PNG images. */
6321 { /* Tell the PNG lib to handle gamma correction for us. */
6324 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6325 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
6326 /* The libpng documentation says this is right in this case. */
6327 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6330 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
6331 /* Image contains gamma information. */
6332 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
6334 /* Use the standard default for the image gamma. */
6335 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6339 /* Handle alpha channel by combining the image with a background
6340 color. Do this only if a real alpha channel is supplied. For
6341 simple transparency, we prefer a clipping mask. */
6344 png_color_16
*image_bg
;
6345 Lisp_Object specified_bg
6346 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6348 if (STRINGP (specified_bg
))
6349 /* The user specified `:background', use that. */
6351 /* W32 version incorrectly used COLORREF here!! ++kfs */
6353 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6355 png_color_16 user_bg
;
6357 bzero (&user_bg
, sizeof user_bg
);
6358 user_bg
.red
= color
.red
>> 8;
6359 user_bg
.green
= color
.green
>> 8;
6360 user_bg
.blue
= color
.blue
>> 8;
6362 fn_png_set_background (png_ptr
, &user_bg
,
6363 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6366 /* The commented-out code checked if the png specifies a default
6367 background color, and uses that. Since we use the current
6368 frame background, it is OK for us to ignore this.
6370 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
6371 fn_png_set_background (png_ptr, image_bg,
6372 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6376 /* Image does not contain a background color with which
6377 to combine the image data via an alpha channel. Use
6378 the frame's background instead. */
6379 #ifdef HAVE_X_WINDOWS
6381 png_color_16 frame_background
;
6383 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6384 x_query_color (f
, &color
);
6386 bzero (&frame_background
, sizeof frame_background
);
6387 frame_background
.red
= color
.red
>> 8;
6388 frame_background
.green
= color
.green
>> 8;
6389 frame_background
.blue
= color
.blue
>> 8;
6390 #endif /* HAVE_X_WINDOWS */
6394 png_color_16 frame_background
;
6395 color
= FRAME_BACKGROUND_PIXEL (f
);
6396 #if 0 /* W32 TODO : Colormap support. */
6397 x_query_color (f
, &color
);
6399 bzero (&frame_background
, sizeof frame_background
);
6400 frame_background
.red
= GetRValue (color
);
6401 frame_background
.green
= GetGValue (color
);
6402 frame_background
.blue
= GetBValue (color
);
6403 #endif /* HAVE_NTGUI */
6406 unsigned long color
;
6407 png_color_16 frame_background
;
6408 color
= FRAME_BACKGROUND_PIXEL (f
);
6409 #if 0 /* MAC/W32 TODO : Colormap support. */
6410 x_query_color (f
, &color
);
6412 bzero (&frame_background
, sizeof frame_background
);
6413 frame_background
.red
= RED_FROM_ULONG (color
);
6414 frame_background
.green
= GREEN_FROM_ULONG (color
);
6415 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6418 fn_png_set_background (png_ptr
, &frame_background
,
6419 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6423 /* Update info structure. */
6424 fn_png_read_update_info (png_ptr
, info_ptr
);
6426 /* Get number of channels. Valid values are 1 for grayscale images
6427 and images with a palette, 2 for grayscale images with transparency
6428 information (alpha channel), 3 for RGB images, and 4 for RGB
6429 images with alpha channel, i.e. RGBA. If conversions above were
6430 sufficient we should only have 3 or 4 channels here. */
6431 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6432 xassert (channels
== 3 || channels
== 4);
6434 /* Number of bytes needed for one row of the image. */
6435 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6437 /* Allocate memory for the image. */
6438 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6439 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6440 for (i
= 0; i
< height
; ++i
)
6441 rows
[i
] = pixels
+ i
* row_bytes
;
6443 /* Read the entire image. */
6444 fn_png_read_image (png_ptr
, rows
);
6445 fn_png_read_end (png_ptr
, info_ptr
);
6452 /* Create the X image and pixmap. */
6453 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6457 /* Create an image and pixmap serving as mask if the PNG image
6458 contains an alpha channel. */
6461 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6462 &mask_img
, &img
->mask
))
6464 x_destroy_x_image (ximg
);
6465 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6466 img
->pixmap
= NO_PIXMAP
;
6470 /* Fill the X image and mask from PNG data. */
6471 init_color_table ();
6473 for (y
= 0; y
< height
; ++y
)
6475 png_byte
*p
= rows
[y
];
6477 for (x
= 0; x
< width
; ++x
)
6484 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6485 /* An alpha channel, aka mask channel, associates variable
6486 transparency with an image. Where other image formats
6487 support binary transparency---fully transparent or fully
6488 opaque---PNG allows up to 254 levels of partial transparency.
6489 The PNG library implements partial transparency by combining
6490 the image with a specified background color.
6492 I'm not sure how to handle this here nicely: because the
6493 background on which the image is displayed may change, for
6494 real alpha channel support, it would be necessary to create
6495 a new image for each possible background.
6497 What I'm doing now is that a mask is created if we have
6498 boolean transparency information. Otherwise I'm using
6499 the frame's background color to combine the image with. */
6504 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6510 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6511 /* Set IMG's background color from the PNG image, unless the user
6515 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6517 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6518 img
->background_valid
= 1;
6522 #ifdef COLOR_TABLE_SUPPORT
6523 /* Remember colors allocated for this image. */
6524 img
->colors
= colors_in_color_table (&img
->ncolors
);
6525 free_color_table ();
6526 #endif /* COLOR_TABLE_SUPPORT */
6529 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6534 img
->height
= height
;
6536 /* Maybe fill in the background field while we have ximg handy.
6537 Casting avoids a GCC warning. */
6538 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6540 /* Put the image into the pixmap, then free the X image and its buffer. */
6541 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6542 x_destroy_x_image (ximg
);
6544 /* Same for the mask. */
6547 /* Fill in the background_transparent field while we have the
6548 mask handy. Casting avoids a GCC warning. */
6549 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6551 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6552 x_destroy_x_image (mask_img
);
6559 #else /* HAVE_PNG */
6568 if (MyCGImageCreateWithPNGDataProvider
)
6569 return image_load_quartz2d (f
, img
, 1);
6572 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6576 #endif /* !HAVE_PNG */
6580 /***********************************************************************
6582 ***********************************************************************/
6584 #if defined (HAVE_JPEG) || defined (MAC_OS)
6586 static int jpeg_image_p
P_ ((Lisp_Object object
));
6587 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6589 /* The symbol `jpeg' identifying images of this type. */
6593 /* Indices of image specification fields in gs_format, below. */
6595 enum jpeg_keyword_index
6604 JPEG_HEURISTIC_MASK
,
6610 /* Vector of image_keyword structures describing the format
6611 of valid user-defined image specifications. */
6613 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6615 {":type", IMAGE_SYMBOL_VALUE
, 1},
6616 {":data", IMAGE_STRING_VALUE
, 0},
6617 {":file", IMAGE_STRING_VALUE
, 0},
6618 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6619 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6620 {":relief", IMAGE_INTEGER_VALUE
, 0},
6621 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6622 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6623 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6624 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6627 /* Structure describing the image type `jpeg'. */
6629 static struct image_type jpeg_type
=
6638 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6641 jpeg_image_p (object
)
6644 struct image_keyword fmt
[JPEG_LAST
];
6646 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6648 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6651 /* Must specify either the :data or :file keyword. */
6652 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6655 #endif /* HAVE_JPEG || MAC_OS */
6659 /* Work around a warning about HAVE_STDLIB_H being redefined in
6661 #ifdef HAVE_STDLIB_H
6662 #define HAVE_STDLIB_H_1
6663 #undef HAVE_STDLIB_H
6664 #endif /* HAVE_STLIB_H */
6666 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6667 /* In older releases of the jpeg library, jpeglib.h will define boolean
6668 differently depending on __WIN32__, so make sure it is defined. */
6672 #include <jpeglib.h>
6676 #ifdef HAVE_STLIB_H_1
6677 #define HAVE_STDLIB_H 1
6682 /* JPEG library details. */
6683 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6684 DEF_IMGLIB_FN (jpeg_start_decompress
);
6685 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6686 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6687 DEF_IMGLIB_FN (jpeg_read_header
);
6688 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6689 DEF_IMGLIB_FN (jpeg_std_error
);
6690 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6693 init_jpeg_functions (Lisp_Object libraries
)
6697 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6700 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6701 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6702 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6703 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6704 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6705 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6706 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6707 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6711 /* Wrapper since we can't directly assign the function pointer
6712 to another function pointer that was declared more completely easily. */
6714 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6715 j_decompress_ptr cinfo
;
6718 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6723 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6724 #define fn_jpeg_start_decompress jpeg_start_decompress
6725 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6726 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6727 #define fn_jpeg_read_header jpeg_read_header
6728 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6729 #define fn_jpeg_std_error jpeg_std_error
6730 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6732 #endif /* HAVE_NTGUI */
6734 struct my_jpeg_error_mgr
6736 struct jpeg_error_mgr pub
;
6737 jmp_buf setjmp_buffer
;
6742 my_error_exit (cinfo
)
6745 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6746 longjmp (mgr
->setjmp_buffer
, 1);
6750 /* Init source method for JPEG data source manager. Called by
6751 jpeg_read_header() before any data is actually read. See
6752 libjpeg.doc from the JPEG lib distribution. */
6755 our_common_init_source (cinfo
)
6756 j_decompress_ptr cinfo
;
6761 /* Method to terminate data source. Called by
6762 jpeg_finish_decompress() after all data has been processed. */
6765 our_common_term_source (cinfo
)
6766 j_decompress_ptr cinfo
;
6771 /* Fill input buffer method for JPEG data source manager. Called
6772 whenever more data is needed. We read the whole image in one step,
6773 so this only adds a fake end of input marker at the end. */
6776 our_memory_fill_input_buffer (cinfo
)
6777 j_decompress_ptr cinfo
;
6779 /* Insert a fake EOI marker. */
6780 struct jpeg_source_mgr
*src
= cinfo
->src
;
6781 static JOCTET buffer
[2];
6783 buffer
[0] = (JOCTET
) 0xFF;
6784 buffer
[1] = (JOCTET
) JPEG_EOI
;
6786 src
->next_input_byte
= buffer
;
6787 src
->bytes_in_buffer
= 2;
6792 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6793 is the JPEG data source manager. */
6796 our_memory_skip_input_data (cinfo
, num_bytes
)
6797 j_decompress_ptr cinfo
;
6800 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6804 if (num_bytes
> src
->bytes_in_buffer
)
6805 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6807 src
->bytes_in_buffer
-= num_bytes
;
6808 src
->next_input_byte
+= num_bytes
;
6813 /* Set up the JPEG lib for reading an image from DATA which contains
6814 LEN bytes. CINFO is the decompression info structure created for
6815 reading the image. */
6818 jpeg_memory_src (cinfo
, data
, len
)
6819 j_decompress_ptr cinfo
;
6823 struct jpeg_source_mgr
*src
;
6825 if (cinfo
->src
== NULL
)
6827 /* First time for this JPEG object? */
6828 cinfo
->src
= (struct jpeg_source_mgr
*)
6829 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6830 sizeof (struct jpeg_source_mgr
));
6831 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6832 src
->next_input_byte
= data
;
6835 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6836 src
->init_source
= our_common_init_source
;
6837 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6838 src
->skip_input_data
= our_memory_skip_input_data
;
6839 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6840 src
->term_source
= our_common_term_source
;
6841 src
->bytes_in_buffer
= len
;
6842 src
->next_input_byte
= data
;
6846 struct jpeg_stdio_mgr
6848 struct jpeg_source_mgr mgr
;
6855 /* Size of buffer to read JPEG from file.
6856 Not too big, as we want to use alloc_small. */
6857 #define JPEG_STDIO_BUFFER_SIZE 8192
6860 /* Fill input buffer method for JPEG data source manager. Called
6861 whenever more data is needed. The data is read from a FILE *. */
6864 our_stdio_fill_input_buffer (cinfo
)
6865 j_decompress_ptr cinfo
;
6867 struct jpeg_stdio_mgr
*src
;
6869 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6874 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6876 src
->mgr
.bytes_in_buffer
= bytes
;
6879 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6881 src
->buffer
[0] = (JOCTET
) 0xFF;
6882 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6883 src
->mgr
.bytes_in_buffer
= 2;
6885 src
->mgr
.next_input_byte
= src
->buffer
;
6892 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6893 is the JPEG data source manager. */
6896 our_stdio_skip_input_data (cinfo
, num_bytes
)
6897 j_decompress_ptr cinfo
;
6900 struct jpeg_stdio_mgr
*src
;
6901 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6903 while (num_bytes
> 0 && !src
->finished
)
6905 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6907 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6908 src
->mgr
.next_input_byte
+= num_bytes
;
6913 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6914 src
->mgr
.bytes_in_buffer
= 0;
6915 src
->mgr
.next_input_byte
= NULL
;
6917 our_stdio_fill_input_buffer (cinfo
);
6923 /* Set up the JPEG lib for reading an image from a FILE *.
6924 CINFO is the decompression info structure created for
6925 reading the image. */
6928 jpeg_file_src (cinfo
, fp
)
6929 j_decompress_ptr cinfo
;
6932 struct jpeg_stdio_mgr
*src
;
6934 if (cinfo
->src
!= NULL
)
6935 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6938 /* First time for this JPEG object? */
6939 cinfo
->src
= (struct jpeg_source_mgr
*)
6940 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6941 sizeof (struct jpeg_stdio_mgr
));
6942 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6943 src
->buffer
= (JOCTET
*)
6944 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6945 JPEG_STDIO_BUFFER_SIZE
);
6950 src
->mgr
.init_source
= our_common_init_source
;
6951 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6952 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6953 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6954 src
->mgr
.term_source
= our_common_term_source
;
6955 src
->mgr
.bytes_in_buffer
= 0;
6956 src
->mgr
.next_input_byte
= NULL
;
6960 /* Load image IMG for use on frame F. Patterned after example.c
6961 from the JPEG lib. */
6968 struct jpeg_decompress_struct cinfo
;
6969 struct my_jpeg_error_mgr mgr
;
6970 Lisp_Object file
, specified_file
;
6971 Lisp_Object specified_data
;
6972 FILE * volatile fp
= NULL
;
6974 int row_stride
, x
, y
;
6975 XImagePtr ximg
= NULL
;
6977 unsigned long *colors
;
6979 struct gcpro gcpro1
;
6981 /* Open the JPEG file. */
6982 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6983 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6987 if (NILP (specified_data
))
6989 file
= x_find_image_file (specified_file
);
6990 if (!STRINGP (file
))
6992 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6997 fp
= fopen (SDATA (file
), "rb");
7000 image_error ("Cannot open `%s'", file
, Qnil
);
7006 /* Customize libjpeg's error handling to call my_error_exit when an
7007 error is detected. This function will perform a longjmp.
7008 Casting return value avoids a GCC warning on W32. */
7009 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7010 mgr
.pub
.error_exit
= my_error_exit
;
7012 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7016 /* Called from my_error_exit. Display a JPEG error. */
7017 char buffer
[JMSG_LENGTH_MAX
];
7018 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7019 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7020 build_string (buffer
));
7023 /* Close the input file and destroy the JPEG object. */
7025 fclose ((FILE *) fp
);
7026 fn_jpeg_destroy_decompress (&cinfo
);
7028 /* If we already have an XImage, free that. */
7029 x_destroy_x_image (ximg
);
7031 /* Free pixmap and colors. */
7032 x_clear_image (f
, img
);
7038 /* Create the JPEG decompression object. Let it read from fp.
7039 Read the JPEG image header. */
7040 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7042 if (NILP (specified_data
))
7043 jpeg_file_src (&cinfo
, (FILE *) fp
);
7045 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7046 SBYTES (specified_data
));
7048 fn_jpeg_read_header (&cinfo
, 1);
7050 /* Customize decompression so that color quantization will be used.
7051 Start decompression. */
7052 cinfo
.quantize_colors
= 1;
7053 fn_jpeg_start_decompress (&cinfo
);
7054 width
= img
->width
= cinfo
.output_width
;
7055 height
= img
->height
= cinfo
.output_height
;
7057 if (!check_image_size (f
, width
, height
))
7059 image_error ("Invalid image size", Qnil
, Qnil
);
7060 longjmp (mgr
.setjmp_buffer
, 2);
7063 /* Create X image and pixmap. */
7064 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7065 longjmp (mgr
.setjmp_buffer
, 2);
7067 /* Allocate colors. When color quantization is used,
7068 cinfo.actual_number_of_colors has been set with the number of
7069 colors generated, and cinfo.colormap is a two-dimensional array
7070 of color indices in the range 0..cinfo.actual_number_of_colors.
7071 No more than 255 colors will be generated. */
7075 if (cinfo
.out_color_components
> 2)
7076 ir
= 0, ig
= 1, ib
= 2;
7077 else if (cinfo
.out_color_components
> 1)
7078 ir
= 0, ig
= 1, ib
= 0;
7080 ir
= 0, ig
= 0, ib
= 0;
7082 /* Use the color table mechanism because it handles colors that
7083 cannot be allocated nicely. Such colors will be replaced with
7084 a default color, and we don't have to care about which colors
7085 can be freed safely, and which can't. */
7086 init_color_table ();
7087 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7090 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7092 /* Multiply RGB values with 255 because X expects RGB values
7093 in the range 0..0xffff. */
7094 int r
= cinfo
.colormap
[ir
][i
] << 8;
7095 int g
= cinfo
.colormap
[ig
][i
] << 8;
7096 int b
= cinfo
.colormap
[ib
][i
] << 8;
7097 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7100 #ifdef COLOR_TABLE_SUPPORT
7101 /* Remember those colors actually allocated. */
7102 img
->colors
= colors_in_color_table (&img
->ncolors
);
7103 free_color_table ();
7104 #endif /* COLOR_TABLE_SUPPORT */
7108 row_stride
= width
* cinfo
.output_components
;
7109 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7111 for (y
= 0; y
< height
; ++y
)
7113 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7114 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7115 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7119 fn_jpeg_finish_decompress (&cinfo
);
7120 fn_jpeg_destroy_decompress (&cinfo
);
7122 fclose ((FILE *) fp
);
7124 /* Maybe fill in the background field while we have ximg handy. */
7125 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7126 /* Casting avoids a GCC warning. */
7127 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7129 /* Put the image into the pixmap. */
7130 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7131 x_destroy_x_image (ximg
);
7136 #else /* HAVE_JPEG */
7145 return image_load_quartz2d (f
, img
, 0);
7147 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7152 #endif /* !HAVE_JPEG */
7156 /***********************************************************************
7158 ***********************************************************************/
7160 #if defined (HAVE_TIFF) || defined (MAC_OS)
7162 static int tiff_image_p
P_ ((Lisp_Object object
));
7163 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7165 /* The symbol `tiff' identifying images of this type. */
7169 /* Indices of image specification fields in tiff_format, below. */
7171 enum tiff_keyword_index
7180 TIFF_HEURISTIC_MASK
,
7186 /* Vector of image_keyword structures describing the format
7187 of valid user-defined image specifications. */
7189 static struct image_keyword tiff_format
[TIFF_LAST
] =
7191 {":type", IMAGE_SYMBOL_VALUE
, 1},
7192 {":data", IMAGE_STRING_VALUE
, 0},
7193 {":file", IMAGE_STRING_VALUE
, 0},
7194 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7195 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7196 {":relief", IMAGE_INTEGER_VALUE
, 0},
7197 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7198 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7199 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7200 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7203 /* Structure describing the image type `tiff'. */
7205 static struct image_type tiff_type
=
7214 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7217 tiff_image_p (object
)
7220 struct image_keyword fmt
[TIFF_LAST
];
7221 bcopy (tiff_format
, fmt
, sizeof fmt
);
7223 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7226 /* Must specify either the :data or :file keyword. */
7227 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7230 #endif /* HAVE_TIFF || MAC_OS */
7238 /* TIFF library details. */
7239 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7240 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7241 DEF_IMGLIB_FN (TIFFOpen
);
7242 DEF_IMGLIB_FN (TIFFClientOpen
);
7243 DEF_IMGLIB_FN (TIFFGetField
);
7244 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7245 DEF_IMGLIB_FN (TIFFClose
);
7248 init_tiff_functions (Lisp_Object libraries
)
7252 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7255 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7256 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7257 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7258 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7259 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7260 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7261 LOAD_IMGLIB_FN (library
, TIFFClose
);
7267 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7268 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7269 #define fn_TIFFOpen TIFFOpen
7270 #define fn_TIFFClientOpen TIFFClientOpen
7271 #define fn_TIFFGetField TIFFGetField
7272 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7273 #define fn_TIFFClose TIFFClose
7275 #endif /* HAVE_NTGUI */
7278 /* Reading from a memory buffer for TIFF images Based on the PNG
7279 memory source, but we have to provide a lot of extra functions.
7282 We really only need to implement read and seek, but I am not
7283 convinced that the TIFF library is smart enough not to destroy
7284 itself if we only hand it the function pointers we need to
7289 unsigned char *bytes
;
7296 tiff_read_from_memory (data
, buf
, size
)
7301 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7303 if (size
> src
->len
- src
->index
)
7305 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7311 tiff_write_from_memory (data
, buf
, size
)
7320 tiff_seek_in_memory (data
, off
, whence
)
7325 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7330 case SEEK_SET
: /* Go from beginning of source. */
7334 case SEEK_END
: /* Go from end of source. */
7335 idx
= src
->len
+ off
;
7338 case SEEK_CUR
: /* Go from current position. */
7339 idx
= src
->index
+ off
;
7342 default: /* Invalid `whence'. */
7346 if (idx
> src
->len
|| idx
< 0)
7354 tiff_close_memory (data
)
7362 tiff_mmap_memory (data
, pbase
, psize
)
7367 /* It is already _IN_ memory. */
7372 tiff_unmap_memory (data
, base
, size
)
7377 /* We don't need to do this. */
7381 tiff_size_of_memory (data
)
7384 return ((tiff_memory_source
*) data
)->len
;
7389 tiff_error_handler (title
, format
, ap
)
7390 const char *title
, *format
;
7396 len
= sprintf (buf
, "TIFF error: %s ", title
);
7397 vsprintf (buf
+ len
, format
, ap
);
7398 add_to_log (buf
, Qnil
, Qnil
);
7403 tiff_warning_handler (title
, format
, ap
)
7404 const char *title
, *format
;
7410 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7411 vsprintf (buf
+ len
, format
, ap
);
7412 add_to_log (buf
, Qnil
, Qnil
);
7416 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7424 Lisp_Object file
, specified_file
;
7425 Lisp_Object specified_data
;
7427 int width
, height
, x
, y
;
7431 struct gcpro gcpro1
;
7432 tiff_memory_source memsrc
;
7434 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7435 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7439 fn_TIFFSetErrorHandler (tiff_error_handler
);
7440 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7442 if (NILP (specified_data
))
7444 /* Read from a file */
7445 file
= x_find_image_file (specified_file
);
7446 if (!STRINGP (file
))
7448 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7453 /* Try to open the image file. Casting return value avoids a
7454 GCC warning on W32. */
7455 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7458 image_error ("Cannot open `%s'", file
, Qnil
);
7465 /* Memory source! */
7466 memsrc
.bytes
= SDATA (specified_data
);
7467 memsrc
.len
= SBYTES (specified_data
);
7470 /* Casting return value avoids a GCC warning on W32. */
7471 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7472 (TIFFReadWriteProc
) tiff_read_from_memory
,
7473 (TIFFReadWriteProc
) tiff_write_from_memory
,
7474 tiff_seek_in_memory
,
7476 tiff_size_of_memory
,
7482 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7488 /* Get width and height of the image, and allocate a raster buffer
7489 of width x height 32-bit values. */
7490 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7491 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7493 if (!check_image_size (f
, width
, height
))
7495 image_error ("Invalid image size", Qnil
, Qnil
);
7500 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7502 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7503 fn_TIFFClose (tiff
);
7506 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7512 /* Create the X image and pixmap. */
7513 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7520 /* Initialize the color table. */
7521 init_color_table ();
7523 /* Process the pixel raster. Origin is in the lower-left corner. */
7524 for (y
= 0; y
< height
; ++y
)
7526 uint32
*row
= buf
+ y
* width
;
7528 for (x
= 0; x
< width
; ++x
)
7530 uint32 abgr
= row
[x
];
7531 int r
= TIFFGetR (abgr
) << 8;
7532 int g
= TIFFGetG (abgr
) << 8;
7533 int b
= TIFFGetB (abgr
) << 8;
7534 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7538 #ifdef COLOR_TABLE_SUPPORT
7539 /* Remember the colors allocated for the image. Free the color table. */
7540 img
->colors
= colors_in_color_table (&img
->ncolors
);
7541 free_color_table ();
7542 #endif /* COLOR_TABLE_SUPPORT */
7545 img
->height
= height
;
7547 /* Maybe fill in the background field while we have ximg handy. */
7548 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7549 /* Casting avoids a GCC warning on W32. */
7550 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7552 /* Put the image into the pixmap, then free the X image and its buffer. */
7553 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7554 x_destroy_x_image (ximg
);
7561 #else /* HAVE_TIFF */
7569 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7573 #endif /* !HAVE_TIFF */
7577 /***********************************************************************
7579 ***********************************************************************/
7581 #if defined (HAVE_GIF) || defined (MAC_OS)
7583 static int gif_image_p
P_ ((Lisp_Object object
));
7584 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7585 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7587 /* The symbol `gif' identifying images of this type. */
7591 /* Indices of image specification fields in gif_format, below. */
7593 enum gif_keyword_index
7609 /* Vector of image_keyword structures describing the format
7610 of valid user-defined image specifications. */
7612 static struct image_keyword gif_format
[GIF_LAST
] =
7614 {":type", IMAGE_SYMBOL_VALUE
, 1},
7615 {":data", IMAGE_STRING_VALUE
, 0},
7616 {":file", IMAGE_STRING_VALUE
, 0},
7617 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7618 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7619 {":relief", IMAGE_INTEGER_VALUE
, 0},
7620 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7621 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7622 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7623 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7624 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7627 /* Structure describing the image type `gif'. */
7629 static struct image_type gif_type
=
7638 /* Free X resources of GIF image IMG which is used on frame F. */
7641 gif_clear_image (f
, img
)
7645 /* IMG->data.ptr_val may contain extension data. */
7646 img
->data
.lisp_val
= Qnil
;
7647 x_clear_image (f
, img
);
7650 /* Return non-zero if OBJECT is a valid GIF image specification. */
7653 gif_image_p (object
)
7656 struct image_keyword fmt
[GIF_LAST
];
7657 bcopy (gif_format
, fmt
, sizeof fmt
);
7659 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7662 /* Must specify either the :data or :file keyword. */
7663 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7666 #endif /* HAVE_GIF || MAC_OS */
7670 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7671 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7672 Undefine before redefining to avoid a preprocessor warning. */
7676 /* avoid conflict with QuickdrawText.h */
7677 #define DrawText gif_DrawText
7678 #include <gif_lib.h>
7681 #else /* HAVE_NTGUI || MAC_OS */
7683 #include <gif_lib.h>
7685 #endif /* HAVE_NTGUI || MAC_OS */
7690 /* GIF library details. */
7691 DEF_IMGLIB_FN (DGifCloseFile
);
7692 DEF_IMGLIB_FN (DGifSlurp
);
7693 DEF_IMGLIB_FN (DGifOpen
);
7694 DEF_IMGLIB_FN (DGifOpenFileName
);
7697 init_gif_functions (Lisp_Object libraries
)
7701 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7704 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7705 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7706 LOAD_IMGLIB_FN (library
, DGifOpen
);
7707 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7713 #define fn_DGifCloseFile DGifCloseFile
7714 #define fn_DGifSlurp DGifSlurp
7715 #define fn_DGifOpen DGifOpen
7716 #define fn_DGifOpenFileName DGifOpenFileName
7718 #endif /* HAVE_NTGUI */
7720 /* Reading a GIF image from memory
7721 Based on the PNG memory stuff to a certain extent. */
7725 unsigned char *bytes
;
7731 /* Make the current memory source available to gif_read_from_memory.
7732 It's done this way because not all versions of libungif support
7733 a UserData field in the GifFileType structure. */
7734 static gif_memory_source
*current_gif_memory_src
;
7737 gif_read_from_memory (file
, buf
, len
)
7742 gif_memory_source
*src
= current_gif_memory_src
;
7744 if (len
> src
->len
- src
->index
)
7747 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7753 /* Load GIF image IMG for use on frame F. Value is non-zero if
7761 Lisp_Object file
, specified_file
;
7762 Lisp_Object specified_data
;
7763 int rc
, width
, height
, x
, y
, i
;
7765 ColorMapObject
*gif_color_map
;
7766 unsigned long pixel_colors
[256];
7768 struct gcpro gcpro1
;
7770 int ino
, image_height
, image_width
;
7771 gif_memory_source memsrc
;
7772 unsigned char *raster
;
7774 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7775 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7779 if (NILP (specified_data
))
7781 file
= x_find_image_file (specified_file
);
7782 if (!STRINGP (file
))
7784 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7789 /* Open the GIF file. Casting return value avoids a GCC warning
7791 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7794 image_error ("Cannot open `%s'", file
, Qnil
);
7801 /* Read from memory! */
7802 current_gif_memory_src
= &memsrc
;
7803 memsrc
.bytes
= SDATA (specified_data
);
7804 memsrc
.len
= SBYTES (specified_data
);
7807 /* Casting return value avoids a GCC warning on W32. */
7808 gif
= (GifFileType
*)fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7811 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7817 /* Before reading entire contents, check the declared image size. */
7818 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7820 image_error ("Invalid image size", Qnil
, Qnil
);
7821 fn_DGifCloseFile (gif
);
7826 /* Read entire contents. */
7827 rc
= fn_DGifSlurp (gif
);
7828 if (rc
== GIF_ERROR
)
7830 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7831 fn_DGifCloseFile (gif
);
7836 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7837 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7838 if (ino
>= gif
->ImageCount
)
7840 image_error ("Invalid image number `%s' in image `%s'",
7842 fn_DGifCloseFile (gif
);
7847 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7848 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7849 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7850 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7851 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7852 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7854 width
= img
->width
= max (gif
->SWidth
,
7855 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7856 img
->corners
[RIGHT_CORNER
]));
7857 height
= img
->height
= max (gif
->SHeight
,
7858 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7859 img
->corners
[BOT_CORNER
]));
7861 if (!check_image_size (f
, width
, height
))
7863 image_error ("Invalid image size", Qnil
, Qnil
);
7864 fn_DGifCloseFile (gif
);
7869 /* Create the X image and pixmap. */
7870 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7872 fn_DGifCloseFile (gif
);
7877 /* Allocate colors. */
7878 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7880 gif_color_map
= gif
->SColorMap
;
7881 init_color_table ();
7882 bzero (pixel_colors
, sizeof pixel_colors
);
7884 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7886 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7887 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7888 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7889 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7892 #ifdef COLOR_TABLE_SUPPORT
7893 img
->colors
= colors_in_color_table (&img
->ncolors
);
7894 free_color_table ();
7895 #endif /* COLOR_TABLE_SUPPORT */
7897 /* Clear the part of the screen image that are not covered by
7898 the image from the GIF file. Full animated GIF support
7899 requires more than can be done here (see the gif89 spec,
7900 disposal methods). Let's simply assume that the part
7901 not covered by a sub-image is in the frame's background color. */
7902 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7903 for (x
= 0; x
< width
; ++x
)
7904 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7906 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7907 for (x
= 0; x
< width
; ++x
)
7908 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7910 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7912 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7913 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7914 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7915 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7918 /* Read the GIF image into the X image. We use a local variable
7919 `raster' here because RasterBits below is a char *, and invites
7920 problems with bytes >= 0x80. */
7921 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7923 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7925 static int interlace_start
[] = {0, 4, 2, 1};
7926 static int interlace_increment
[] = {8, 8, 4, 2};
7928 int row
= interlace_start
[0];
7932 for (y
= 0; y
< image_height
; y
++)
7934 if (row
>= image_height
)
7936 row
= interlace_start
[++pass
];
7937 while (row
>= image_height
)
7938 row
= interlace_start
[++pass
];
7941 for (x
= 0; x
< image_width
; x
++)
7943 int i
= raster
[(y
* image_width
) + x
];
7944 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7945 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7948 row
+= interlace_increment
[pass
];
7953 for (y
= 0; y
< image_height
; ++y
)
7954 for (x
= 0; x
< image_width
; ++x
)
7956 int i
= raster
[y
* image_width
+ x
];
7957 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7958 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7962 /* Save GIF image extension data for `image-extension-data'.
7963 Format is (count IMAGES FUNCTION "BYTES" ...). */
7964 img
->data
.lisp_val
= Qnil
;
7965 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7967 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7968 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7969 /* Append (... FUNCTION "BYTES") */
7970 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7971 Fcons (make_number (ext
->Function
),
7972 img
->data
.lisp_val
));
7973 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7975 if (gif
->ImageCount
> 1)
7976 img
->data
.lisp_val
= Fcons (Qcount
,
7977 Fcons (make_number (gif
->ImageCount
),
7978 img
->data
.lisp_val
));
7980 fn_DGifCloseFile (gif
);
7982 /* Maybe fill in the background field while we have ximg handy. */
7983 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7984 /* Casting avoids a GCC warning. */
7985 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7987 /* Put the image into the pixmap, then free the X image and its buffer. */
7988 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7989 x_destroy_x_image (ximg
);
7995 #else /* !HAVE_GIF */
8003 Lisp_Object specified_file
, file
;
8004 Lisp_Object specified_data
;
8006 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8014 Lisp_Object specified_bg
;
8019 TimeScale time_scale
;
8020 TimeValue time
, duration
;
8025 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8026 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8028 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8031 if (NILP (specified_data
))
8033 /* Read from a file */
8037 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8041 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8046 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8047 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8051 if (!graphic_p
&& !movie_p
)
8053 if (prefer_graphic_p
)
8054 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8055 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8058 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8059 CloseMovieFile (refnum
);
8062 image_error ("Error reading `%s'", file
, Qnil
);
8068 /* Memory source! */
8070 long file_type_atom
[3];
8072 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8075 image_error ("Cannot allocate data handle for `%s'",
8080 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8081 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8082 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8083 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8086 err
= PtrAndHand ("\p", dref
, 1);
8088 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8091 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8094 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8095 &movie_p
, &prefer_graphic_p
, 0);
8099 if (!graphic_p
&& !movie_p
)
8101 if (prefer_graphic_p
)
8105 DisposeHandle (dref
);
8106 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8110 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8111 HandleDataHandlerSubType
);
8112 DisposeHandle (dref
);
8117 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8118 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8119 track
= GetMovieIndTrack (movie
, 1);
8120 media
= GetTrackMedia (track
);
8121 nsamples
= GetMediaSampleCount (media
);
8122 if (ino
>= nsamples
)
8124 image_error ("Invalid image number `%s' in image `%s'",
8128 time_scale
= GetMediaTimeScale (media
);
8130 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8131 if (!STRINGP (specified_bg
) ||
8132 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8134 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8135 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8136 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8137 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8139 GetMovieBox (movie
, &rect
);
8140 width
= img
->width
= rect
.right
- rect
.left
;
8141 height
= img
->height
= rect
.bottom
- rect
.top
;
8142 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8145 GetGWorld (&old_port
, &old_gdh
);
8146 SetGWorld (ximg
, NULL
);
8147 bg_color
.red
= color
.red
;
8148 bg_color
.green
= color
.green
;
8149 bg_color
.blue
= color
.blue
;
8150 RGBBackColor (&bg_color
);
8151 SetGWorld (old_port
, old_gdh
);
8152 SetMovieActive (movie
, 1);
8153 SetMovieGWorld (movie
, ximg
, NULL
);
8154 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8155 SetMovieTimeValue (movie
, time
);
8156 MoviesTask (movie
, 0L);
8157 DisposeTrackMedia (media
);
8158 DisposeMovieTrack (track
);
8159 DisposeMovie (movie
);
8163 /* Save GIF image extension data for `image-extension-data'.
8164 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8166 Lisp_Object gce
= make_uninit_string (4);
8167 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8169 /* Fill the delay time field. */
8170 SSET (gce
, 1, centisec
& 0xff);
8171 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8172 /* We don't know about other fields. */
8176 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8177 make_number (0xf9), gce
);
8180 /* Maybe fill in the background field while we have ximg handy. */
8181 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8182 IMAGE_BACKGROUND (img
, f
, ximg
);
8184 /* Put the image into the pixmap. */
8185 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8186 x_destroy_x_image (ximg
);
8190 image_error ("Cannot open `%s'", file
, Qnil
);
8193 DisposeTrackMedia (media
);
8195 DisposeMovieTrack (track
);
8197 DisposeMovie (movie
);
8204 #endif /* HAVE_GIF */
8208 /***********************************************************************
8210 ***********************************************************************/
8212 #if defined (HAVE_RSVG)
8214 /* Function prototypes. */
8216 static int svg_image_p
P_ ((Lisp_Object object
));
8217 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8219 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8220 unsigned char *, unsigned int));
8222 /* The symbol `svg' identifying images of this type. */
8226 /* Indices of image specification fields in svg_format, below. */
8228 enum svg_keyword_index
8243 /* Vector of image_keyword structures describing the format
8244 of valid user-defined image specifications. */
8246 static struct image_keyword svg_format
[SVG_LAST
] =
8248 {":type", IMAGE_SYMBOL_VALUE
, 1},
8249 {":data", IMAGE_STRING_VALUE
, 0},
8250 {":file", IMAGE_STRING_VALUE
, 0},
8251 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8252 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8253 {":relief", IMAGE_INTEGER_VALUE
, 0},
8254 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8255 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8256 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8257 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8260 /* Structure describing the image type `svg'. Its the same type of
8261 structure defined for all image formats, handled by emacs image
8262 functions. See struct image_type in dispextern.h. */
8264 static struct image_type svg_type
=
8266 /* An identifier showing that this is an image structure for the SVG format. */
8268 /* Handle to a function that can be used to identify a SVG file. */
8270 /* Handle to function used to load a SVG file. */
8272 /* Handle to function to free sresources for SVG. */
8274 /* An internal field to link to the next image type in a list of
8275 image types, will be filled in when registering the format. */
8280 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8281 this by calling parse_image_spec and supplying the keywords that
8282 identify the SVG format. */
8285 svg_image_p (object
)
8288 struct image_keyword fmt
[SVG_LAST
];
8289 bcopy (svg_format
, fmt
, sizeof fmt
);
8291 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8294 /* Must specify either the :data or :file keyword. */
8295 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8298 #include <librsvg/rsvg.h>
8300 /* TO DO: define DEF_IMGLIB_FN here. This macro is used to handle
8301 loading of dynamic link library functions for various OS:es.
8302 Currently only librsvg2 is supported, which is only available for X,
8303 so its not strictly necessary yet. The current code is thought to be
8304 compatible with this scheme because of the defines below, should
8305 librsvg2 become available on more plattforms. */
8307 #define fn_rsvg_handle_new rsvg_handle_new
8308 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8309 #define fn_rsvg_handle_write rsvg_handle_write
8310 #define fn_rsvg_handle_close rsvg_handle_close
8311 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8312 #define fn_rsvg_handle_free rsvg_handle_free
8314 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8315 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8316 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8317 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8318 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8319 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8320 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8321 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8324 /* Load SVG image IMG for use on frame F. Value is non-zero if
8325 successful. this function will go into the svg_type structure, and
8326 the prototype thus needs to be compatible with that structure. */
8334 Lisp_Object file_name
;
8336 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8337 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8338 if (STRINGP (file_name
))
8341 unsigned char *contents
;
8343 struct gcpro gcpro1
;
8345 file
= x_find_image_file (file_name
);
8347 if (!STRINGP (file
))
8349 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8354 /* Read the entire file into memory. */
8355 contents
= slurp_file (SDATA (file
), &size
);
8356 if (contents
== NULL
)
8358 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8362 /* If the file was slurped into memory properly, parse it. */
8363 success_p
= svg_load_image (f
, img
, contents
, size
);
8367 /* Else its not a file, its a lisp object. Load the image from a
8368 lisp object rather than a file. */
8373 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8374 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8380 /* svg_load_image is a helper function for svg_load, which does the actual
8381 loading given contents and size, apart from frame and image
8382 structures, passed from svg_load.
8384 Uses librsvg to do most of the image processing.
8386 Returns non-zero when sucessful. */
8388 svg_load_image (f
, img
, contents
, size
)
8389 /* Pointer to emacs frame sturcture. */
8391 /* Pointer to emacs image structure. */
8393 /* String containing the SVG XML data to be parsed. */
8394 unsigned char *contents
;
8395 /* Size of data in bytes. */
8398 RsvgHandle
*rsvg_handle
;
8399 GError
*error
= NULL
;
8403 const guint8
*pixels
;
8406 Lisp_Object specified_bg
;
8411 /* g_type_init is a glib function that must be called prior to using
8412 gnome type library functions. */
8414 /* Make a handle to a new rsvg object. */
8415 rsvg_handle
= fn_rsvg_handle_new ();
8417 /* Parse the contents argument and fill in the rsvg_handle. */
8418 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8422 /* The parsing is complete, rsvg_handle is ready to used, close it
8423 for further writes. */
8424 fn_rsvg_handle_close (rsvg_handle
, &error
);
8427 /* We can now get a valid pixel buffer from the svg file, if all
8429 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8432 /* Extract some meta data from the svg handle. */
8433 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8434 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8435 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8436 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8438 /* Validate the svg meta data. */
8439 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8440 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8441 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8442 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8444 /* Try to create a x pixmap to hold the svg pixmap. */
8445 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8447 g_object_unref (pixbuf
);
8451 init_color_table ();
8453 /* Handle alpha channel by combining the image with a background
8455 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8456 if (STRINGP (specified_bg
)
8457 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8459 background
.red
>>= 8;
8460 background
.green
>>= 8;
8461 background
.blue
>>= 8;
8465 #ifdef HAVE_X_WINDOWS
8466 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8467 x_query_color (f
, &background
);
8469 /* SVG pixmaps specify transparency in the last byte, so right
8470 shift 8 bits to get rid of it, since emacs doesnt support
8472 background
.red
>>= 8;
8473 background
.green
>>= 8;
8474 background
.blue
>>= 8;
8475 #elif defined (MAC_OS)
8476 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8477 background
.red
= RED_FROM_ULONG (background
.pixel
);
8478 background
.green
= GREEN_FROM_ULONG (background
.pixel
);
8479 background
.blue
= BLUE_FROM_ULONG (background
.pixel
);
8480 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8485 /* This loop handles opacity values, since Emacs assumes
8486 non-transparent images. Each pixel must be "flattened" by
8487 calculating he resulting color, given the transparency of the
8488 pixel, and the image background color. */
8489 for (y
= 0; y
< height
; ++y
)
8491 for (x
= 0; x
< width
; ++x
)
8501 opacity
= *pixels
++;
8503 red
= ((red
* opacity
)
8504 + (background
.red
* ((1 << 8) - opacity
)));
8505 green
= ((green
* opacity
)
8506 + (background
.green
* ((1 << 8) - opacity
)));
8507 blue
= ((blue
* opacity
)
8508 + (background
.blue
* ((1 << 8) - opacity
)));
8510 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8513 pixels
+= rowstride
- 4 * width
;
8516 #ifdef COLOR_TABLE_SUPPORT
8517 /* Remember colors allocated for this image. */
8518 img
->colors
= colors_in_color_table (&img
->ncolors
);
8519 free_color_table ();
8520 #endif /* COLOR_TABLE_SUPPORT */
8522 g_object_unref (pixbuf
);
8525 img
->height
= height
;
8527 /* Maybe fill in the background field while we have ximg handy.
8528 Casting avoids a GCC warning. */
8529 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8531 /* Put the image into the pixmap, then free the X image and its
8533 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8534 x_destroy_x_image (ximg
);
8539 /* FIXME: Use error->message so the user knows what is the actual
8540 problem with the image. */
8541 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8542 g_error_free (error
);
8546 #endif /* defined (HAVE_RSVG) */
8551 /***********************************************************************
8553 ***********************************************************************/
8555 #ifdef HAVE_X_WINDOWS
8556 #define HAVE_GHOSTSCRIPT 1
8557 #endif /* HAVE_X_WINDOWS */
8559 /* The symbol `postscript' identifying images of this type. */
8561 Lisp_Object Qpostscript
;
8563 #ifdef HAVE_GHOSTSCRIPT
8565 static int gs_image_p
P_ ((Lisp_Object object
));
8566 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8567 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8569 /* Keyword symbols. */
8571 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8573 /* Indices of image specification fields in gs_format, below. */
8575 enum gs_keyword_index
8593 /* Vector of image_keyword structures describing the format
8594 of valid user-defined image specifications. */
8596 static struct image_keyword gs_format
[GS_LAST
] =
8598 {":type", IMAGE_SYMBOL_VALUE
, 1},
8599 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8600 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8601 {":file", IMAGE_STRING_VALUE
, 1},
8602 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8603 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8604 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8605 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8606 {":relief", IMAGE_INTEGER_VALUE
, 0},
8607 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8608 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8609 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8610 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8613 /* Structure describing the image type `ghostscript'. */
8615 static struct image_type gs_type
=
8625 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8628 gs_clear_image (f
, img
)
8632 /* IMG->data.ptr_val may contain a recorded colormap. */
8633 xfree (img
->data
.ptr_val
);
8634 x_clear_image (f
, img
);
8638 /* Return non-zero if OBJECT is a valid Ghostscript image
8645 struct image_keyword fmt
[GS_LAST
];
8649 bcopy (gs_format
, fmt
, sizeof fmt
);
8651 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8654 /* Bounding box must be a list or vector containing 4 integers. */
8655 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8658 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8659 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8664 else if (VECTORP (tem
))
8666 if (XVECTOR (tem
)->size
!= 4)
8668 for (i
= 0; i
< 4; ++i
)
8669 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8679 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8688 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8689 struct gcpro gcpro1
, gcpro2
;
8691 double in_width
, in_height
;
8692 Lisp_Object pixel_colors
= Qnil
;
8694 /* Compute pixel size of pixmap needed from the given size in the
8695 image specification. Sizes in the specification are in pt. 1 pt
8696 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8698 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8699 in_width
= XFASTINT (pt_width
) / 72.0;
8700 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8701 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8702 in_height
= XFASTINT (pt_height
) / 72.0;
8703 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8705 if (!check_image_size (f
, img
->width
, img
->height
))
8707 image_error ("Invalid image size", Qnil
, Qnil
);
8711 /* Create the pixmap. */
8712 xassert (img
->pixmap
== NO_PIXMAP
);
8714 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8716 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8717 img
->width
, img
->height
,
8718 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8723 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8727 /* Call the loader to fill the pixmap. It returns a process object
8728 if successful. We do not record_unwind_protect here because
8729 other places in redisplay like calling window scroll functions
8730 don't either. Let the Lisp loader use `unwind-protect' instead. */
8731 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8733 sprintf (buffer
, "%lu %lu",
8734 (unsigned long) FRAME_X_WINDOW (f
),
8735 (unsigned long) img
->pixmap
);
8736 window_and_pixmap_id
= build_string (buffer
);
8738 sprintf (buffer
, "%lu %lu",
8739 FRAME_FOREGROUND_PIXEL (f
),
8740 FRAME_BACKGROUND_PIXEL (f
));
8741 pixel_colors
= build_string (buffer
);
8743 XSETFRAME (frame
, f
);
8744 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8746 loader
= intern ("gs-load-image");
8748 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8749 make_number (img
->width
),
8750 make_number (img
->height
),
8751 window_and_pixmap_id
,
8754 return PROCESSP (img
->data
.lisp_val
);
8758 /* Kill the Ghostscript process that was started to fill PIXMAP on
8759 frame F. Called from XTread_socket when receiving an event
8760 telling Emacs that Ghostscript has finished drawing. */
8763 x_kill_gs_process (pixmap
, f
)
8767 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8771 /* Find the image containing PIXMAP. */
8772 for (i
= 0; i
< c
->used
; ++i
)
8773 if (c
->images
[i
]->pixmap
== pixmap
)
8776 /* Should someone in between have cleared the image cache, for
8777 instance, give up. */
8781 /* Kill the GS process. We should have found PIXMAP in the image
8782 cache and its image should contain a process object. */
8784 xassert (PROCESSP (img
->data
.lisp_val
));
8785 Fkill_process (img
->data
.lisp_val
, Qnil
);
8786 img
->data
.lisp_val
= Qnil
;
8788 #if defined (HAVE_X_WINDOWS)
8790 /* On displays with a mutable colormap, figure out the colors
8791 allocated for the image by looking at the pixels of an XImage for
8793 class = FRAME_X_VISUAL (f
)->class;
8794 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8800 /* Try to get an XImage for img->pixmep. */
8801 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8802 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8807 /* Initialize the color table. */
8808 init_color_table ();
8810 /* For each pixel of the image, look its color up in the
8811 color table. After having done so, the color table will
8812 contain an entry for each color used by the image. */
8813 for (y
= 0; y
< img
->height
; ++y
)
8814 for (x
= 0; x
< img
->width
; ++x
)
8816 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8817 lookup_pixel_color (f
, pixel
);
8820 /* Record colors in the image. Free color table and XImage. */
8821 #ifdef COLOR_TABLE_SUPPORT
8822 img
->colors
= colors_in_color_table (&img
->ncolors
);
8823 free_color_table ();
8825 XDestroyImage (ximg
);
8827 #if 0 /* This doesn't seem to be the case. If we free the colors
8828 here, we get a BadAccess later in x_clear_image when
8829 freeing the colors. */
8830 /* We have allocated colors once, but Ghostscript has also
8831 allocated colors on behalf of us. So, to get the
8832 reference counts right, free them once. */
8834 x_free_colors (f
, img
->colors
, img
->ncolors
);
8838 image_error ("Cannot get X image of `%s'; colors will not be freed",
8843 #endif /* HAVE_X_WINDOWS */
8845 /* Now that we have the pixmap, compute mask and transform the
8846 image if requested. */
8848 postprocess_image (f
, img
);
8852 #endif /* HAVE_GHOSTSCRIPT */
8855 /***********************************************************************
8857 ***********************************************************************/
8861 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8862 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8866 return valid_image_p (spec
) ? Qt
: Qnil
;
8870 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8876 if (valid_image_p (spec
))
8877 id
= lookup_image (SELECTED_FRAME (), spec
);
8880 return make_number (id
);
8883 #endif /* GLYPH_DEBUG != 0 */
8886 /***********************************************************************
8888 ***********************************************************************/
8891 /* Image types that rely on external libraries are loaded dynamically
8892 if the library is available. */
8893 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8894 define_image_type (image_type, init_lib_fn (libraries))
8896 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8897 define_image_type (image_type, 1)
8898 #endif /* HAVE_NTGUI */
8900 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8901 doc
: /* Initialize image library implementing image type TYPE.
8902 Return non-nil if TYPE is a supported image type.
8904 Image types pbm and xbm are prebuilt; other types are loaded here.
8905 Libraries to load are specified in alist LIBRARIES (usually, the value
8906 of `image-library-alist', which see). */)
8908 Lisp_Object type
, libraries
;
8912 /* Don't try to reload the library. */
8913 tested
= Fassq (type
, Vimage_type_cache
);
8915 return XCDR (tested
);
8917 #if defined (HAVE_XPM) || defined (MAC_OS)
8918 if (EQ (type
, Qxpm
))
8919 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8922 #if defined (HAVE_JPEG) || defined (MAC_OS)
8923 if (EQ (type
, Qjpeg
))
8924 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8927 #if defined (HAVE_TIFF) || defined (MAC_OS)
8928 if (EQ (type
, Qtiff
))
8929 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8932 #if defined (HAVE_GIF) || defined (MAC_OS)
8933 if (EQ (type
, Qgif
))
8934 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8937 #if defined (HAVE_PNG) || defined (MAC_OS)
8938 if (EQ (type
, Qpng
))
8939 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8942 #if defined (HAVE_RSVG)
8943 if (EQ (type
, Qsvg
))
8944 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
8947 #ifdef HAVE_GHOSTSCRIPT
8948 if (EQ (type
, Qpostscript
))
8949 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8952 /* If the type is not recognized, avoid testing it ever again. */
8953 CACHE_IMAGE_TYPE (type
, Qnil
);
8960 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8962 /* Initialize this only once, since that's what we do with Vimage_types
8963 and they are supposed to be in sync. Initializing here gives correct
8964 operation on GNU/Linux of calling dump-emacs after loading some images. */
8967 /* Must be defined now becase we're going to update it below, while
8968 defining the supported image types. */
8969 DEFVAR_LISP ("image-types", &Vimage_types
,
8970 doc
: /* List of potentially supported image types.
8971 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8972 To check whether it is really supported, use `image-type-available-p'. */);
8973 Vimage_types
= Qnil
;
8975 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8976 doc
: /* Alist of image types vs external libraries needed to display them.
8978 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8979 representing a supported image type, and the rest are strings giving
8980 alternate filenames for the corresponding external libraries.
8982 Emacs tries to load the libraries in the order they appear on the
8983 list; if none is loaded, the running session of Emacs won't
8984 support the image type. Types 'pbm and 'xbm don't need to be
8985 listed; they're always supported. */);
8986 Vimage_library_alist
= Qnil
;
8987 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8989 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8990 doc
: /* Maximum size of images.
8991 Emacs will not load an image into memory if its pixel width or
8992 pixel height exceeds this limit.
8994 If the value is an integer, it directly specifies the maximum
8995 image height and width, measured in pixels. If it is a floating
8996 point number, it specifies the maximum image height and width
8997 as a ratio to the frame height and width. If the value is
8998 non-numeric, there is no explicit limit on the size of images. */);
8999 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9001 Vimage_type_cache
= Qnil
;
9002 staticpro (&Vimage_type_cache
);
9004 Qpbm
= intern ("pbm");
9006 ADD_IMAGE_TYPE(Qpbm
);
9008 Qxbm
= intern ("xbm");
9010 ADD_IMAGE_TYPE(Qxbm
);
9012 define_image_type (&xbm_type
, 1);
9013 define_image_type (&pbm_type
, 1);
9015 QCascent
= intern (":ascent");
9016 staticpro (&QCascent
);
9017 QCmargin
= intern (":margin");
9018 staticpro (&QCmargin
);
9019 QCrelief
= intern (":relief");
9020 staticpro (&QCrelief
);
9021 QCconversion
= intern (":conversion");
9022 staticpro (&QCconversion
);
9023 QCcolor_symbols
= intern (":color-symbols");
9024 staticpro (&QCcolor_symbols
);
9025 QCheuristic_mask
= intern (":heuristic-mask");
9026 staticpro (&QCheuristic_mask
);
9027 QCindex
= intern (":index");
9028 staticpro (&QCindex
);
9029 QCmatrix
= intern (":matrix");
9030 staticpro (&QCmatrix
);
9031 QCcolor_adjustment
= intern (":color-adjustment");
9032 staticpro (&QCcolor_adjustment
);
9033 QCmask
= intern (":mask");
9034 staticpro (&QCmask
);
9036 Qlaplace
= intern ("laplace");
9037 staticpro (&Qlaplace
);
9038 Qemboss
= intern ("emboss");
9039 staticpro (&Qemboss
);
9040 Qedge_detection
= intern ("edge-detection");
9041 staticpro (&Qedge_detection
);
9042 Qheuristic
= intern ("heuristic");
9043 staticpro (&Qheuristic
);
9045 Qpostscript
= intern ("postscript");
9046 staticpro (&Qpostscript
);
9047 #ifdef HAVE_GHOSTSCRIPT
9048 ADD_IMAGE_TYPE(Qpostscript
);
9049 QCloader
= intern (":loader");
9050 staticpro (&QCloader
);
9051 QCbounding_box
= intern (":bounding-box");
9052 staticpro (&QCbounding_box
);
9053 QCpt_width
= intern (":pt-width");
9054 staticpro (&QCpt_width
);
9055 QCpt_height
= intern (":pt-height");
9056 staticpro (&QCpt_height
);
9057 #endif /* HAVE_GHOSTSCRIPT */
9059 #if defined (HAVE_XPM) || defined (MAC_OS)
9060 Qxpm
= intern ("xpm");
9062 ADD_IMAGE_TYPE(Qxpm
);
9065 #if defined (HAVE_JPEG) || defined (MAC_OS)
9066 Qjpeg
= intern ("jpeg");
9068 ADD_IMAGE_TYPE(Qjpeg
);
9071 #if defined (HAVE_TIFF) || defined (MAC_OS)
9072 Qtiff
= intern ("tiff");
9074 ADD_IMAGE_TYPE(Qtiff
);
9077 #if defined (HAVE_GIF) || defined (MAC_OS)
9078 Qgif
= intern ("gif");
9080 ADD_IMAGE_TYPE(Qgif
);
9083 #if defined (HAVE_PNG) || defined (MAC_OS)
9084 Qpng
= intern ("png");
9086 ADD_IMAGE_TYPE(Qpng
);
9089 #if defined (HAVE_RSVG)
9090 Qsvg
= intern ("svg");
9092 ADD_IMAGE_TYPE(Qsvg
);
9095 defsubr (&Sinit_image_library
);
9096 defsubr (&Sclear_image_cache
);
9097 defsubr (&Simage_refresh
);
9098 defsubr (&Simage_size
);
9099 defsubr (&Simage_mask_p
);
9100 defsubr (&Simage_extension_data
);
9104 defsubr (&Slookup_image
);
9107 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9108 doc
: /* Non-nil means always draw a cross over disabled images.
9109 Disabled images are those having an `:conversion disabled' property.
9110 A cross is always drawn on black & white displays. */);
9111 cross_disabled_images
= 0;
9113 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9114 doc
: /* List of directories to search for window system bitmap files. */);
9115 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9117 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9118 doc
: /* Time after which cached images are removed from the cache.
9119 When an image has not been displayed this many seconds, remove it
9120 from the image cache. Value must be an integer or nil with nil
9121 meaning don't clear the cache. */);
9122 Vimage_cache_eviction_delay
= make_number (30 * 60);
9128 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
9129 init_image_func_pointer ();
9133 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9134 (do not change this comment) */